~ubuntu-branches/ubuntu/natty/nat/natty

« back to all changes in this revision

Viewing changes to util.c

  • Committer: Bazaar Package Importer
  • Author(s): Javier Fernandez-Sanguino Pen~a
  • Date: 2003-04-03 23:09:28 UTC
  • Revision ID: james.westby@ubuntu.com-20030403230928-17uovylnn0v0566q
Tags: upstream-1.0
ImportĀ upstreamĀ versionĀ 1.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * This file has been modified from the original Samba package
 
3
 * by Secure Networks Inc., January and February, 1997.  This package and
 
4
 * all code which it is based on falls under the GNU Public License
 
5
 * agreement.
 
6
 */
 
7
 
 
8
/* 
 
9
   Unix SMB/Netbios implementation.
 
10
   Version 1.9.
 
11
   Samba utility functions
 
12
   Copyright (C) Andrew Tridgell 1992-1995
 
13
   
 
14
   This program is free software; you can redistribute it and/or modify
 
15
   it under the terms of the GNU General Public License as published by
 
16
   the Free Software Foundation; either version 2 of the License, or
 
17
   (at your option) any later version.
 
18
   
 
19
   This program is distributed in the hope that it will be useful,
 
20
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
21
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
22
   GNU General Public License for more details.
 
23
   
 
24
   You should have received a copy of the GNU General Public License
 
25
   along with this program; if not, write to the Free Software
 
26
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
27
*/
 
28
 
 
29
#include "includes.h"
 
30
#include "loadparm.h"
 
31
 
 
32
#ifdef _WIN32
 
33
 #include <sys/socket.h>
 
34
#endif 
 
35
 
 
36
pstring scope = "";
 
37
 
 
38
int DEBUGLEVEL = 0;
 
39
 
 
40
BOOL passive = False;
 
41
 
 
42
int Protocol = PROTOCOL_COREPLUS;
 
43
 
 
44
int serverzone=0;
 
45
 
 
46
/* a default finfo structure to ensure all fields are sensible */
 
47
file_info def_finfo = {-1,0,0,0,0,0,0,""};
 
48
 
 
49
/* these are some file handles where debug info will be stored */
 
50
FILE *dbf = NULL;
 
51
 
 
52
/* the client file descriptor */
 
53
int Client = -1;
 
54
 
 
55
/* info on the client */
 
56
struct from_host Client_info=
 
57
{"UNKNOWN","0.0.0.0",NULL};
 
58
 
 
59
/* the last IP received from */
 
60
struct in_addr lastip;
 
61
 
 
62
/* the last port received from */
 
63
int lastport=0;
 
64
 
 
65
/* my IP, the broadcast IP and the Netmask */
 
66
struct in_addr myip;
 
67
struct in_addr bcast_ip;
 
68
struct in_addr Netmask;
 
69
 
 
70
int trans_num = 0;
 
71
 
 
72
/*
 
73
   case handling on filenames 
 
74
*/
 
75
int case_default = CASE_LOWER;
 
76
 
 
77
 
 
78
/* size of reads during a direct file to file transfer */
 
79
int ReadSize = 16*1024;
 
80
 
 
81
pstring debugf = "/tmp/log.samba";
 
82
int syslog_level;
 
83
 
 
84
/* the following control case operations - they are put here so the
 
85
   client can link easily */
 
86
BOOL case_sensitive;
 
87
BOOL case_preserve;
 
88
BOOL use_mangled_map = False;
 
89
BOOL short_case_preserve;
 
90
BOOL case_mangle;
 
91
 
 
92
fstring remote_machine="";
 
93
fstring local_machine="";
 
94
fstring remote_arch="UNKNOWN";
 
95
fstring remote_proto="UNKNOWN";
 
96
pstring myhostname="";
 
97
pstring user_socket_options="";   
 
98
pstring sesssetup_user="";
 
99
 
 
100
 
 
101
static char *filename_dos(char *path,char *buf);
 
102
 
 
103
static BOOL stdout_logging = False;
 
104
 
 
105
#ifdef SCANNER
 
106
#undef exit
 
107
#define exit(x) return(0)
 
108
#endif /* SCANNER */
 
109
 
 
110
/*******************************************************************
 
111
  get ready for syslog stuff
 
112
  ******************************************************************/
 
113
void setup_logging(char *pname,BOOL interactive)
 
114
{
 
115
#ifdef SYSLOG
 
116
  if (!interactive) {
 
117
    char *p = strrchr(pname,'/');
 
118
    if (p) pname = p+1;
 
119
    openlog(pname, LOG_PID, LOG_DAEMON);
 
120
  }
 
121
#endif
 
122
  if (interactive) {
 
123
    stdout_logging = True;
 
124
    dbf = stdout;
 
125
  }
 
126
}
 
127
 
 
128
 
 
129
BOOL append_log=False;
 
130
 
 
131
/*******************************************************************
 
132
write an debug message on the debugfile. This is called by the DEBUG
 
133
macro
 
134
********************************************************************/
 
135
#ifdef __STDC__
 
136
int Debug1(char *format_str, ...)
 
137
{
 
138
#else
 
139
int Debug1(va_alist)
 
140
va_dcl
 
141
{  
 
142
  char *format_str;
 
143
#endif
 
144
  va_list ap;  
 
145
  
 
146
#ifdef __STDC__
 
147
  va_start(ap, format_str);
 
148
#else
 
149
  va_start(ap);
 
150
  format_str = va_arg(ap,char *);
 
151
#endif
 
152
 
 
153
  if (stdout_logging) {
 
154
    vfprintf(dbf,format_str,ap);
 
155
    va_end(ap);
 
156
    return(0);
 
157
  }
 
158
 
 
159
#ifndef SCANNER
 
160
  {
 
161
    static int debug_count=0;
 
162
 
 
163
    debug_count++;
 
164
    if (debug_count == 100) {
 
165
      int maxlog = lp_max_log_size() * 1024;
 
166
      if (dbf && maxlog > 0)
 
167
        {
 
168
          struct stat st;
 
169
 
 
170
          if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) {
 
171
            fclose(dbf); dbf = NULL;
 
172
            reopen_logs();
 
173
            if (dbf && file_size(debugf) > maxlog) {
 
174
              pstring name;
 
175
              fclose(dbf); dbf = NULL;
 
176
              sprintf(name,"%s.old",debugf);
 
177
              sys_rename(debugf,name);
 
178
              reopen_logs();
 
179
            }
 
180
          }
 
181
        }
 
182
      debug_count=0;
 
183
    }
 
184
  }
 
185
  
 
186
#ifdef SYSLOG
 
187
  if (!lp_syslog_only())
 
188
#endif  
 
189
    {
 
190
      if (!dbf) 
 
191
        {
 
192
          dbf = fopen(debugf,"w");
 
193
          if (dbf)
 
194
            setbuf(dbf,NULL);
 
195
          else
 
196
            return(0);
 
197
        }
 
198
    }
 
199
 
 
200
#ifdef SYSLOG
 
201
  if (syslog_level < lp_syslog())
 
202
    {
 
203
      /* 
 
204
       * map debug levels to syslog() priorities
 
205
       * note that not all DEBUG(0, ...) calls are
 
206
       * necessarily errors
 
207
       */
 
208
      static int priority_map[] = { 
 
209
        LOG_ERR,     /* 0 */
 
210
        LOG_WARNING, /* 1 */
 
211
        LOG_NOTICE,  /* 2 */
 
212
        LOG_INFO,    /* 3 */
 
213
      };
 
214
      int priority;
 
215
      pstring msgbuf;
 
216
      
 
217
      if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) ||
 
218
          syslog_level < 0)
 
219
        priority = LOG_DEBUG;
 
220
      else
 
221
        priority = priority_map[syslog_level];
 
222
      
 
223
      vsprintf(msgbuf, format_str, ap);
 
224
      
 
225
      msgbuf[255] = '\0';
 
226
      syslog(priority, "%s", msgbuf);
 
227
    }
 
228
#endif
 
229
  
 
230
#ifdef SYSLOG
 
231
  if (!lp_syslog_only())
 
232
#endif
 
233
    {
 
234
      vfprintf(dbf,format_str,ap);
 
235
      fflush(dbf);
 
236
    }
 
237
  
 
238
  va_end(ap);
 
239
  return(0);
 
240
#endif /* SCANNER */
 
241
}
 
242
 
 
243
/****************************************************************************
 
244
routine to do file locking
 
245
****************************************************************************/
 
246
BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
 
247
{
 
248
#if HAVE_FCNTL_LOCK
 
249
  struct flock lock;
 
250
  int ret;
 
251
 
 
252
#if 1
 
253
  uint32 mask = 0xC0000000;
 
254
 
 
255
  /* make sure the count is reasonable, we might kill the lockd otherwise */
 
256
  count &= ~mask;
 
257
 
 
258
  /* the offset is often strange - remove 2 of its bits if either of
 
259
     the top two bits are set. Shift the top ones by two bits. This
 
260
     still allows OLE2 apps to operate, but should stop lockd from
 
261
     dieing */
 
262
  if ((offset & mask) != 0)
 
263
    offset = (offset & ~mask) | ((offset & mask) >> 2);
 
264
#else
 
265
  unsigned long mask = ((unsigned)1<<31);
 
266
 
 
267
  /* interpret negative counts as large numbers */
 
268
  if (count < 0)
 
269
    count &= ~mask;
 
270
 
 
271
  /* no negative offsets */
 
272
  offset &= ~mask;
 
273
 
 
274
  /* count + offset must be in range */
 
275
  while ((offset < 0 || (offset + count < 0)) && mask)
 
276
    {
 
277
      offset &= ~mask;
 
278
      mask = mask >> 1;
 
279
    }
 
280
#endif
 
281
 
 
282
 
 
283
  DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
 
284
 
 
285
  lock.l_type = type;
 
286
  lock.l_whence = SEEK_SET;
 
287
  lock.l_start = (int)offset;
 
288
  lock.l_len = (int)count;
 
289
  lock.l_pid = 0;
 
290
 
 
291
  errno = 0;
 
292
 
 
293
  ret = fcntl(fd,op,&lock);
 
294
 
 
295
  if (errno != 0)
 
296
    DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
 
297
 
 
298
  /* a lock query */
 
299
  if (op == F_GETLK)
 
300
    {
 
301
      if ((ret != -1) &&
 
302
          (lock.l_type != F_UNLCK) && 
 
303
          (lock.l_pid != 0) && 
 
304
          (lock.l_pid != getpid()))
 
305
        {
 
306
          DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
 
307
          return(True);
 
308
        }
 
309
 
 
310
      /* it must be not locked or locked by me */
 
311
      return(False);
 
312
    }
 
313
 
 
314
  /* a lock set or unset */
 
315
  if (ret == -1)
 
316
    {
 
317
      DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
 
318
               offset,count,op,type,strerror(errno)));
 
319
 
 
320
      /* perhaps it doesn't support this sort of locking?? */
 
321
      if (errno == EINVAL)
 
322
        {
 
323
          DEBUG(3,("locking not supported? returning True\n"));
 
324
          return(True);
 
325
        }
 
326
 
 
327
      return(False);
 
328
    }
 
329
 
 
330
  /* everything went OK */
 
331
  DEBUG(5,("Lock call successful\n"));
 
332
 
 
333
  return(True);
 
334
#else
 
335
  return(False);
 
336
#endif
 
337
}
 
338
 
 
339
/*******************************************************************
 
340
lock a file - returning a open file descriptor or -1 on failure
 
341
The timeout is in seconds. 0 means no timeout
 
342
********************************************************************/
 
343
int file_lock(char *name,int timeout)
 
344
{  
 
345
  int fd = open(name,O_RDWR|O_CREAT,0666);
 
346
  time_t t=0;
 
347
  if (fd < 0) return(-1);
 
348
 
 
349
#if HAVE_FCNTL_LOCK
 
350
  if (timeout) t = time(NULL);
 
351
  while (!timeout || (time(NULL)-t < timeout)) {
 
352
    if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);    
 
353
    msleep(LOCK_RETRY_TIMEOUT);
 
354
  }
 
355
  return(-1);
 
356
#else
 
357
  return(fd);
 
358
#endif
 
359
}
 
360
 
 
361
/*******************************************************************
 
362
unlock a file locked by file_lock
 
363
********************************************************************/
 
364
void file_unlock(int fd)
 
365
{
 
366
  if (fd<0) return;
 
367
#if HAVE_FCNTL_LOCK
 
368
  fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
 
369
#endif
 
370
  close(fd);
 
371
}
 
372
 
 
373
/*******************************************************************
 
374
a gettimeofday wrapper
 
375
********************************************************************/
 
376
void GetTimeOfDay(struct timeval *tval)
 
377
{
 
378
#ifdef GETTIMEOFDAY1
 
379
  gettimeofday(tval);
 
380
#else
 
381
  gettimeofday(tval,NULL);
 
382
#endif
 
383
}
 
384
 
 
385
int extra_time_offset = 0;
 
386
 
 
387
static int timediff = 0;
 
388
 
 
389
/*******************************************************************
 
390
init the time differences
 
391
********************************************************************/
 
392
void TimeInit(void)
 
393
{
 
394
  struct tm tm_utc,tm_local;
 
395
  time_t t;
 
396
 
 
397
  t = time(NULL);
 
398
 
 
399
  tm_utc = *(gmtime(&t));
 
400
  tm_local = *(localtime(&t));
 
401
 
 
402
#ifdef HAVE_GMTOFF
 
403
  timediff = -tm_local.tm_gmtoff;  
 
404
#else
 
405
  timediff = mktime(&tm_utc) - mktime(&tm_local);
 
406
#endif
 
407
 
 
408
  if (serverzone == 0) {
 
409
    serverzone = timediff - DSTDiff(t);
 
410
    DEBUG(4,("Serverzone is %d\n",serverzone));
 
411
  }
 
412
}
 
413
 
 
414
 
 
415
/*******************************************************************
 
416
return the DST offset for a particular time
 
417
We keep a table of DST offsets to prevent calling localtime() on each 
 
418
call of this function. This saves a LOT of time on many unixes.
 
419
********************************************************************/
 
420
int DSTDiff(time_t t)
 
421
{
 
422
  static struct dst_table {time_t start,end; BOOL is_dst;} *dst_table = NULL;
 
423
  static int table_size = 0;
 
424
  int i;
 
425
  BOOL is_dst = False;
 
426
 
 
427
  if (t == 0) t = time(NULL);
 
428
 
 
429
#ifndef NO_ISDST
 
430
  for (i=0;i<table_size;i++)
 
431
    if (t >= dst_table[i].start && t <= dst_table[i].end) break;
 
432
 
 
433
  if (i<table_size) {
 
434
    is_dst = dst_table[i].is_dst;
 
435
  } else {
 
436
    time_t low,high;
 
437
 
 
438
    dst_table = (struct dst_table *)Realloc(dst_table,
 
439
                                              sizeof(dst_table[0])*(i+1));
 
440
    if (!dst_table) {
 
441
      table_size = 0;
 
442
      return(0);
 
443
    }
 
444
 
 
445
    table_size++;
 
446
 
 
447
    dst_table[i].is_dst = is_dst = (localtime(&t)->tm_isdst?True:False);;
 
448
    dst_table[i].start = dst_table[i].end = t;
 
449
    
 
450
    /* no entry will cover more than 6 months */
 
451
    low = t - 3*30*24*60*60;
 
452
    high = t + 3*30*24*60*60;
 
453
 
 
454
    /* widen the new entry using two bisection searches */
 
455
    while (low+60*60 < dst_table[i].start) {
 
456
      t = low + (dst_table[i].start-low)/2;
 
457
      if ((localtime(&t)->tm_isdst?True:False) == is_dst)
 
458
        dst_table[i].start = t;
 
459
      else
 
460
        low = t;
 
461
    }
 
462
 
 
463
    while (high-60*60 > dst_table[i].end) {
 
464
      t = high + (high-dst_table[i].end)/2;
 
465
      if ((localtime(&t)->tm_isdst?True:False) == is_dst)
 
466
        dst_table[i].end = t;
 
467
      else
 
468
        high = t;
 
469
    }    
 
470
 
 
471
/*
 
472
    DEBUG(1,("Added DST entry from %s ",
 
473
             asctime(localtime(&dst_table[i].start))));
 
474
    DEBUG(1,("to %s (%d)\n",asctime(localtime(&dst_table[i].end)),
 
475
             dst_table[i].is_dst));
 
476
*/
 
477
  }
 
478
#endif
 
479
 
 
480
  return((is_dst?60*60:0) - (extra_time_offset*60));
 
481
}
 
482
 
 
483
/****************************************************************************
 
484
return the difference between local and GMT time
 
485
****************************************************************************/
 
486
int TimeDiff(time_t t)
 
487
{
 
488
  static BOOL initialised = False;
 
489
  if (!initialised) {initialised=True; TimeInit();}
 
490
  return(timediff - DSTDiff(t));
 
491
}
 
492
 
 
493
/****************************************************************************
 
494
try to optimise the localtime call, it can be quite expenive on some machines
 
495
timemul is normally LOCAL_TO_GMT, GMT_TO_LOCAL or 0
 
496
****************************************************************************/
 
497
struct tm *LocalTime(time_t *t,int timemul)
 
498
{
 
499
  time_t t2 = *t;
 
500
 
 
501
  if (timemul)
 
502
    t2 += timemul * TimeDiff(t2);
 
503
 
 
504
  return(gmtime(&t2));
 
505
}
 
506
 
 
507
 
 
508
/****************************************************************************
 
509
determine if a file descriptor is in fact a socket
 
510
****************************************************************************/
 
511
BOOL is_a_socket(int fd)
 
512
{
 
513
  int v,l;
 
514
  l = sizeof(int);
 
515
#ifdef _WIN32
 
516
  /* evil, but it works */
 
517
  return(0);
 
518
#else
 
519
  return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
 
520
#endif  
 
521
}
 
522
 
 
523
 
 
524
/****************************************************************************
 
525
  Get the next token from a string, return False if none found
 
526
  handles double-quotes. 
 
527
Based on a routine by GJC@VILLAGE.COM. 
 
528
Extensively modified by Andrew.Tridgell@anu.edu.au
 
529
****************************************************************************/
 
530
BOOL next_token(char **ptr,char *buff,char *sep)
 
531
{
 
532
  static char *last_ptr=NULL;
 
533
  char *s;
 
534
  BOOL quoted;
 
535
 
 
536
  if (!ptr) ptr = &last_ptr;
 
537
  if (!ptr) return(False);
 
538
 
 
539
  s = *ptr;
 
540
 
 
541
  /* default to simple separators */
 
542
  if (!sep) sep = " \t\n\r";
 
543
 
 
544
  /* find the first non sep char */
 
545
  while(*s && strchr(sep,*s)) s++;
 
546
 
 
547
  /* nothing left? */
 
548
  if (! *s) return(False);
 
549
 
 
550
  /* copy over the token */
 
551
  for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
 
552
    {
 
553
      if (*s == '\"') 
 
554
        quoted = !quoted;
 
555
      else
 
556
        *buff++ = *s;
 
557
    }
 
558
 
 
559
  *ptr = (*s) ? s+1 : s;  
 
560
  *buff = 0;
 
561
  last_ptr = *ptr;
 
562
 
 
563
  return(True);
 
564
}
 
565
 
 
566
/*******************************************************************
 
567
safely copies memory, ensuring no overlap problems.
 
568
this is only used if the machine does not have it's own memmove().
 
569
this is not the fastest algorithm in town, but it will do for our
 
570
needs.
 
571
********************************************************************/
 
572
void *MemMove(void *dest,void *src,int size)
 
573
{
 
574
  unsigned long d,s;
 
575
  int i;
 
576
  if (dest==src || !size) return(dest);
 
577
 
 
578
  d = (unsigned long)dest;
 
579
  s = (unsigned long)src;
 
580
 
 
581
  if ((d >= (s+size)) || (s >= (d+size))) {
 
582
    /* no overlap */
 
583
    memcpy(dest,src,size);
 
584
    return(dest);
 
585
  }
 
586
 
 
587
  if (d < s)
 
588
    {
 
589
      /* we can forward copy */
 
590
      if (s-d >= sizeof(int) && 
 
591
          !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
 
592
        /* do it all as words */
 
593
        int *idest = (int *)dest;
 
594
        int *isrc = (int *)src;
 
595
        size /= sizeof(int);
 
596
        for (i=0;i<size;i++) idest[i] = isrc[i];
 
597
      } else {
 
598
        /* simplest */
 
599
        char *cdest = (char *)dest;
 
600
        char *csrc = (char *)src;
 
601
        for (i=0;i<size;i++) cdest[i] = csrc[i];
 
602
      }
 
603
    }
 
604
  else
 
605
    {
 
606
      /* must backward copy */
 
607
      if (d-s >= sizeof(int) && 
 
608
          !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
 
609
        /* do it all as words */
 
610
        int *idest = (int *)dest;
 
611
        int *isrc = (int *)src;
 
612
        size /= sizeof(int);
 
613
        for (i=size-1;i>=0;i--) idest[i] = isrc[i];
 
614
      } else {
 
615
        /* simplest */
 
616
        char *cdest = (char *)dest;
 
617
        char *csrc = (char *)src;
 
618
        for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
 
619
      }      
 
620
    }
 
621
  return(dest);
 
622
}
 
623
 
 
624
 
 
625
/****************************************************************************
 
626
prompte a dptr (to make it recently used)
 
627
****************************************************************************/
 
628
void array_promote(char *array,int elsize,int element)
 
629
{
 
630
  char *p;
 
631
  if (element == 0)
 
632
    return;
 
633
 
 
634
  p = (char *)malloc(elsize);
 
635
 
 
636
  if (!p)
 
637
    {
 
638
      DEBUG(5,("Ahh! Can't malloc\n"));
 
639
      return;
 
640
    }
 
641
  memcpy(p,array + element * elsize, elsize);
 
642
  memmove(array + elsize,array,elsize*element);
 
643
  memcpy(array,p,elsize);
 
644
  free(p);
 
645
}
 
646
 
 
647
enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
 
648
 
 
649
struct
 
650
{
 
651
  char *name;
 
652
  int level;
 
653
  int option;
 
654
  int value;
 
655
  int opttype;
 
656
} socket_options[] = {
 
657
  {"SO_KEEPALIVE",      SOL_SOCKET,    SO_KEEPALIVE,    0,                 OPT_BOOL},
 
658
  {"SO_REUSEADDR",      SOL_SOCKET,    SO_REUSEADDR,    0,                 OPT_BOOL},
 
659
  {"SO_BROADCAST",      SOL_SOCKET,    SO_BROADCAST,    0,                 OPT_BOOL},
 
660
#ifdef TCP_NODELAY
 
661
  {"TCP_NODELAY",       IPPROTO_TCP,   TCP_NODELAY,     0,                 OPT_BOOL},
 
662
#endif
 
663
#ifdef IPTOS_LOWDELAY
 
664
  {"IPTOS_LOWDELAY",    IPPROTO_IP,    IP_TOS,          IPTOS_LOWDELAY,    OPT_ON},
 
665
#endif
 
666
#ifdef IPTOS_THROUGHPUT
 
667
  {"IPTOS_THROUGHPUT",  IPPROTO_IP,    IP_TOS,          IPTOS_THROUGHPUT,  OPT_ON},
 
668
#endif
 
669
#ifdef SO_SNDBUF
 
670
  {"SO_SNDBUF",         SOL_SOCKET,    SO_SNDBUF,       0,                 OPT_INT},
 
671
#endif
 
672
#ifdef SO_RCVBUF
 
673
  {"SO_RCVBUF",         SOL_SOCKET,    SO_RCVBUF,       0,                 OPT_INT},
 
674
#endif
 
675
#ifdef SO_SNDLOWAT
 
676
  {"SO_SNDLOWAT",       SOL_SOCKET,    SO_SNDLOWAT,     0,                 OPT_INT},
 
677
#endif
 
678
#ifdef SO_RCVLOWAT
 
679
  {"SO_RCVLOWAT",       SOL_SOCKET,    SO_RCVLOWAT,     0,                 OPT_INT},
 
680
#endif
 
681
  {NULL,0,0,0,0}};
 
682
 
 
683
        
 
684
 
 
685
/****************************************************************************
 
686
set user socket options
 
687
****************************************************************************/
 
688
void set_socket_options(int fd, char *options)
 
689
{
 
690
  string tok;
 
691
 
 
692
  while (next_token(&options,tok," \t,"))
 
693
    {
 
694
      int ret=0,i;
 
695
      int value = 1;
 
696
      char *p;
 
697
      BOOL got_value = False;
 
698
 
 
699
      if ((p = strchr(tok,'=')))
 
700
        {
 
701
          *p = 0;
 
702
          value = atoi(p+1);
 
703
          got_value = True;
 
704
        }
 
705
 
 
706
      for (i=0;socket_options[i].name;i++)
 
707
        if (strequal(socket_options[i].name,tok))
 
708
          break;
 
709
 
 
710
      if (!socket_options[i].name)
 
711
        {
 
712
          DEBUG(0,("Unknown socket option %s\n",tok));
 
713
          continue;
 
714
        }
 
715
 
 
716
      switch (socket_options[i].opttype)
 
717
        {
 
718
        case OPT_BOOL:
 
719
        case OPT_INT:
 
720
          ret = setsockopt(fd,socket_options[i].level,
 
721
                           socket_options[i].option,(char *)&value,sizeof(int));
 
722
          break;
 
723
 
 
724
        case OPT_ON:
 
725
          if (got_value)
 
726
            DEBUG(0,("syntax error - %s does not take a value\n",tok));
 
727
 
 
728
          {
 
729
            int on = socket_options[i].value;
 
730
            ret = setsockopt(fd,socket_options[i].level,
 
731
                             socket_options[i].option,(char *)&on,sizeof(int));
 
732
          }
 
733
          break;          
 
734
        }
 
735
      
 
736
      if (ret != 0)
 
737
        DEBUG(0,("Failed to set socket option %s\n",tok));
 
738
    }
 
739
}
 
740
 
 
741
 
 
742
 
 
743
/****************************************************************************
 
744
  close the socket communication
 
745
****************************************************************************/
 
746
void close_sockets(void )
 
747
{
 
748
  close(Client);
 
749
#ifdef SCANNER
 
750
  Client = -1;
 
751
#else
 
752
  Client = 0;
 
753
#endif /* SCANNER */
 
754
}
 
755
 
 
756
/****************************************************************************
 
757
  return the date and time as a string
 
758
****************************************************************************/
 
759
char *timestring(void )
 
760
{
 
761
  static char TimeBuf[100];
 
762
  time_t t;
 
763
  t = time(NULL);
 
764
#ifdef NO_STRFTIME
 
765
  strcpy(TimeBuf, asctime(LocalTime(&t,GMT_TO_LOCAL)));
 
766
#elif defined(CLIX) || defined(CONVEX)
 
767
  strftime(TimeBuf,100,"%m/%d/%y %I:%M:%S %p",LocalTime(&t,GMT_TO_LOCAL));
 
768
#elif defined(AMPM)
 
769
  strftime(TimeBuf,100,"%D %r",LocalTime(&t,GMT_TO_LOCAL));
 
770
#elif defined(TZ_TIME)
 
771
  {
 
772
    strftime(TimeBuf,100,"%D:%T",LocalTime(&t,0));
 
773
    sprintf(TimeBuf+strlen(TimeBuf)," %+03d%02d",
 
774
            -TimeDiff(t)/(60*60),-(TimeDiff(t)/60)%60);
 
775
  }
 
776
#else
 
777
  strftime(TimeBuf,100,"%D %T",LocalTime(&t,GMT_TO_LOCAL));
 
778
#endif
 
779
  return(TimeBuf);
 
780
}
 
781
 
 
782
/****************************************************************************
 
783
determine whether we are in the specified group
 
784
****************************************************************************/
 
785
BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
 
786
{
 
787
  int i;
 
788
 
 
789
  if (group == current_gid) return(True);
 
790
 
 
791
  for (i=0;i<ngroups;i++)
 
792
    if (group == groups[i])
 
793
      return(True);
 
794
 
 
795
  return(False);
 
796
}
 
797
 
 
798
/****************************************************************************
 
799
this is a safer strcpy(), meant to prevent core dumps when nasty things happen
 
800
****************************************************************************/
 
801
char *StrCpy(char *dest,char *src)
 
802
{
 
803
  char *d = dest;
 
804
 
 
805
#if AJT
 
806
  /* I don't want to get lazy with these ... */
 
807
  if (!dest || !src) {
 
808
    DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
 
809
    ajt_panic();
 
810
  }
 
811
#endif
 
812
 
 
813
  if (!dest) return(NULL);
 
814
  if (!src) {
 
815
    *dest = 0;
 
816
    return(dest);
 
817
  }
 
818
  while ((*d++ = *src++)) ;
 
819
  return(dest);
 
820
}
 
821
 
 
822
/****************************************************************************
 
823
line strncpy but always null terminates. Make sure there is room!
 
824
****************************************************************************/
 
825
char *StrnCpy(char *dest,const char *src,int n)
 
826
{
 
827
  char *d = dest;
 
828
  if (!dest) return(NULL);
 
829
  if (!src) {
 
830
    *dest = 0;
 
831
    return(dest);
 
832
  }
 
833
  while (n-- && (*d++ = *src++)) ;
 
834
  *d = 0;
 
835
  return(dest);
 
836
}
 
837
 
 
838
 
 
839
/*******************************************************************
 
840
copy an IP address from one buffer to another
 
841
********************************************************************/
 
842
void putip(void *dest,void *src)
 
843
{
 
844
  memcpy(dest,src,4);
 
845
}
 
846
 
 
847
 
 
848
/****************************************************************************
 
849
interpret the weird netbios "name". Return the name type
 
850
****************************************************************************/
 
851
static int name_interpret(char *in,char *out)
 
852
{
 
853
  int ret;
 
854
  int len = (*in++) / 2;
 
855
 
 
856
  *out=0;
 
857
 
 
858
  if (len > 30 || len<1) return(0);
 
859
 
 
860
  while (len--)
 
861
    {
 
862
      if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
 
863
        *out = 0;
 
864
        return(0);
 
865
      }
 
866
      *out = ((in[0]-'A')<<4) + (in[1]-'A');
 
867
      in += 2;
 
868
      out++;
 
869
    }
 
870
  *out = 0;
 
871
  ret = out[-1];
 
872
 
 
873
#ifdef NETBIOS_SCOPE
 
874
  /* Handle any scope names */
 
875
  while(*in) 
 
876
    {
 
877
      *out++ = '.'; /* Scope names are separated by periods */
 
878
      len = *(unsigned char *)in++;
 
879
      StrnCpy(out, in, len);
 
880
      out += len;
 
881
      *out=0;
 
882
      in += len;
 
883
    }
 
884
#endif
 
885
  return(ret);
 
886
}
 
887
 
 
888
/****************************************************************************
 
889
mangle a name into netbios format
 
890
****************************************************************************/
 
891
int name_mangle(char *In,char *Out,char name_type)
 
892
{
 
893
  fstring name;
 
894
  char buf[20];
 
895
  char *in = (char *)&buf[0];
 
896
  char *out = (char *)Out;
 
897
  char *p, *label;
 
898
  int i;
 
899
 
 
900
#ifdef SCANNER
 
901
  if ((In[0] == '*') && (In[1] == '\0')) {
 
902
    buf[0]='*';
 
903
    memset(&buf[1],0,16);
 
904
  } else {
 
905
    StrnCpy(name,In,sizeof(name)-1);
 
906
    sprintf(buf,"%-15.15s%c",name,name_type);
 
907
  }
 
908
#else
 
909
  if (In[0] != '*') {
 
910
    StrnCpy(name,In,sizeof(name)-1);
 
911
    sprintf(buf,"%-15.15s%c",name,name_type);
 
912
  } else {
 
913
    buf[0]='*';
 
914
    memset(&buf[1],0,16);
 
915
  }
 
916
#endif /* SCANNER */
 
917
 
 
918
  *out++ = 32;
 
919
  for (i=0;i<16;i++) {
 
920
    char c = toupper(in[i]);
 
921
    out[i*2] = (c>>4) + 'A';
 
922
    out[i*2+1] = (c & 0xF) + 'A';
 
923
  }
 
924
  out[32]=0;
 
925
  out += 32;
 
926
  
 
927
  label = scope;
 
928
  while (*label)
 
929
    {
 
930
      p = strchr(label, '.');
 
931
      if (p == 0)
 
932
        p = label + strlen(label);
 
933
      *out++ = p - label;
 
934
      memcpy(out, label, p - label);
 
935
      out += p - label;
 
936
      label += p - label + (*p == '.');
 
937
    }
 
938
  *out = 0;
 
939
  return(name_len(Out));
 
940
}
 
941
 
 
942
 
 
943
/*******************************************************************
 
944
  check if a file exists
 
945
********************************************************************/
 
946
BOOL file_exist(char *fname,struct stat *sbuf)
 
947
{
 
948
  struct stat st;
 
949
  if (!sbuf) sbuf = &st;
 
950
  
 
951
  if (sys_stat(fname,sbuf) != 0) 
 
952
    return(False);
 
953
 
 
954
  return(S_ISREG(sbuf->st_mode));
 
955
}
 
956
 
 
957
/*******************************************************************
 
958
check a files mod time
 
959
********************************************************************/
 
960
time_t file_modtime(char *fname)
 
961
{
 
962
  struct stat st;
 
963
  
 
964
  if (sys_stat(fname,&st) != 0) 
 
965
    return(0);
 
966
 
 
967
  return(st.st_mtime);
 
968
}
 
969
 
 
970
/*******************************************************************
 
971
  check if a directory exists
 
972
********************************************************************/
 
973
BOOL directory_exist(char *dname,struct stat *st)
 
974
{
 
975
  struct stat st2;
 
976
  if (!st) st = &st2;
 
977
 
 
978
  if (sys_stat(dname,st) != 0) 
 
979
    return(False);
 
980
 
 
981
  return(S_ISDIR(st->st_mode));
 
982
}
 
983
 
 
984
/*******************************************************************
 
985
returns the size in bytes of the named file
 
986
********************************************************************/
 
987
uint32 file_size(char *file_name)
 
988
{
 
989
  struct stat buf;
 
990
  buf.st_size = 0;
 
991
  sys_stat(file_name,&buf);
 
992
  return(buf.st_size);
 
993
}
 
994
 
 
995
/****************************************************************************
 
996
check if it's a null mtime
 
997
****************************************************************************/
 
998
static BOOL null_mtime(time_t mtime)
 
999
{
 
1000
  if (mtime == 0 || mtime == 0xFFFFFFFF)
 
1001
    return(True);
 
1002
  return(False);
 
1003
}
 
1004
 
 
1005
/*******************************************************************
 
1006
  create a 16 bit dos packed date
 
1007
********************************************************************/
 
1008
static uint16 make_dos_date1(time_t unixdate,struct tm *t)
 
1009
{
 
1010
  uint16 ret=0;
 
1011
  ret = (((unsigned)(t->tm_mon+1)) >> 3) | ((t->tm_year-80) << 1);
 
1012
  ret = ((ret&0xFF)<<8) | (t->tm_mday | (((t->tm_mon+1) & 0x7) << 5));
 
1013
  return(ret);
 
1014
}
 
1015
 
 
1016
/*******************************************************************
 
1017
  create a 16 bit dos packed time
 
1018
********************************************************************/
 
1019
static uint16 make_dos_time1(time_t unixdate,struct tm *t)
 
1020
{
 
1021
  uint16 ret=0;
 
1022
  ret = ((((unsigned)t->tm_min >> 3)&0x7) | (((unsigned)t->tm_hour) << 3));
 
1023
  ret = ((ret&0xFF)<<8) | ((t->tm_sec/2) | ((t->tm_min & 0x7) << 5));
 
1024
  return(ret);
 
1025
}
 
1026
 
 
1027
/*******************************************************************
 
1028
  create a 32 bit dos packed date/time from some parameters
 
1029
  This takes a GMT time and returns a packed localtime structure
 
1030
********************************************************************/
 
1031
static uint32 make_dos_date(time_t unixdate)
 
1032
{
 
1033
  struct tm *t;
 
1034
  uint32 ret=0;
 
1035
 
 
1036
  t = LocalTime(&unixdate,GMT_TO_LOCAL);
 
1037
 
 
1038
  ret = make_dos_date1(unixdate,t);
 
1039
  ret = ((ret&0xFFFF)<<16) | make_dos_time1(unixdate,t);
 
1040
 
 
1041
  return(ret);
 
1042
}
 
1043
 
 
1044
/*******************************************************************
 
1045
put a dos date into a buffer (time/date format)
 
1046
This takes GMT time and puts local time in the buffer
 
1047
********************************************************************/
 
1048
void put_dos_date(char *buf,int offset,time_t unixdate)
 
1049
{
 
1050
  uint32 x = make_dos_date(unixdate);
 
1051
  SIVAL(buf,offset,x);
 
1052
}
 
1053
 
 
1054
/*******************************************************************
 
1055
put a dos date into a buffer (date/time format)
 
1056
This takes GMT time and puts local time in the buffer
 
1057
********************************************************************/
 
1058
void put_dos_date2(char *buf,int offset,time_t unixdate)
 
1059
{
 
1060
  uint32 x = make_dos_date(unixdate);
 
1061
  x = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 
1062
  SIVAL(buf,offset,x);
 
1063
}
 
1064
 
 
1065
/*******************************************************************
 
1066
put a dos 32 bit "unix like" date into a buffer. This routine takes
 
1067
GMT and converts it to LOCAL time before putting it (most SMBs assume
 
1068
localtime for this sort of date)
 
1069
********************************************************************/
 
1070
void put_dos_date3(char *buf,int offset,time_t unixdate)
 
1071
{
 
1072
  if (!null_mtime(unixdate))
 
1073
    unixdate += GMT_TO_LOCAL*TimeDiff(unixdate);
 
1074
  SIVAL(buf,offset,unixdate);
 
1075
}
 
1076
 
 
1077
/*******************************************************************
 
1078
  interpret a 32 bit dos packed date/time to some parameters
 
1079
********************************************************************/
 
1080
static void interpret_dos_date(uint32 date,int *year,int *month,int *day,int *hour,int *minute,int *second)
 
1081
{
 
1082
  uint32 p0,p1,p2,p3;
 
1083
 
 
1084
  p0=date&0xFF; p1=((date&0xFF00)>>8)&0xFF; 
 
1085
  p2=((date&0xFF0000)>>16)&0xFF; p3=((date&0xFF000000)>>24)&0xFF;
 
1086
 
 
1087
  *second = 2*(p0 & 0x1F);
 
1088
  *minute = ((p0>>5)&0xFF) + ((p1&0x7)<<3);
 
1089
  *hour = (p1>>3)&0xFF;
 
1090
  *day = (p2&0x1F);
 
1091
  *month = ((p2>>5)&0xFF) + ((p3&0x1)<<3) - 1;
 
1092
  *year = ((p3>>1)&0xFF) + 80;
 
1093
}
 
1094
 
 
1095
/*******************************************************************
 
1096
  create a unix date (int GMT) from a dos date (which is actually in
 
1097
  localtime)
 
1098
********************************************************************/
 
1099
time_t make_unix_date(void *date_ptr)
 
1100
{
 
1101
  uint32 dos_date=0;
 
1102
  struct tm t;
 
1103
  time_t ret;
 
1104
 
 
1105
  dos_date = IVAL(date_ptr,0);
 
1106
 
 
1107
  if (dos_date == 0) return(0);
 
1108
  
 
1109
  interpret_dos_date(dos_date,&t.tm_year,&t.tm_mon,
 
1110
                     &t.tm_mday,&t.tm_hour,&t.tm_min,&t.tm_sec);
 
1111
  t.tm_wday = 1;
 
1112
  t.tm_yday = 1;
 
1113
  t.tm_isdst = -1;
 
1114
  
 
1115
  /* mktime() also does the local to GMT time conversion for us. XXXXX
 
1116
     Do all unixes do this the same?? */
 
1117
  ret = mktime(&t);
 
1118
 
 
1119
  return(ret);
 
1120
}
 
1121
 
 
1122
/*******************************************************************
 
1123
like make_unix_date() but the words are reversed
 
1124
********************************************************************/
 
1125
time_t make_unix_date2(void *date_ptr)
 
1126
{
 
1127
  uint32 x,x2;
 
1128
 
 
1129
  x = IVAL(date_ptr,0);
 
1130
  x2 = ((x&0xFFFF)<<16) | ((x&0xFFFF0000)>>16);
 
1131
  SIVAL(&x,0,x2);
 
1132
 
 
1133
  return(make_unix_date((void *)&x));
 
1134
}
 
1135
 
 
1136
/*******************************************************************
 
1137
  create a unix GMT date from a dos date in 32 bit "unix like" format
 
1138
these generally arrive as localtimes, with corresponding DST
 
1139
********************************************************************/
 
1140
time_t make_unix_date3(void *date_ptr)
 
1141
{
 
1142
  time_t t = IVAL(date_ptr,0);
 
1143
  if (!null_mtime(t))
 
1144
    t += LOCAL_TO_GMT*TimeDiff(t);
 
1145
  return(t);
 
1146
}
 
1147
 
 
1148
/*******************************************************************
 
1149
return a string representing an attribute for a file
 
1150
********************************************************************/
 
1151
char *attrib_string(int mode)
 
1152
{
 
1153
  static char attrstr[10];
 
1154
 
 
1155
  attrstr[0] = 0;
 
1156
 
 
1157
  if (mode & aVOLID) strcat(attrstr,"V");
 
1158
  if (mode & aDIR) strcat(attrstr,"D");
 
1159
  if (mode & aARCH) strcat(attrstr,"A");
 
1160
  if (mode & aHIDDEN) strcat(attrstr,"H");
 
1161
  if (mode & aSYSTEM) strcat(attrstr,"S");
 
1162
  if (mode & aRONLY) strcat(attrstr,"R");         
 
1163
 
 
1164
  return(attrstr);
 
1165
}
 
1166
 
 
1167
 
 
1168
/*******************************************************************
 
1169
  case insensitive string compararison
 
1170
********************************************************************/
 
1171
int StrCaseCmp(char *s, char *t)
 
1172
{
 
1173
  for (; tolower(*s) == tolower(*t); ++s, ++t)
 
1174
    if (!*s) return 0;
 
1175
 
 
1176
  return tolower(*s) - tolower(*t);
 
1177
}
 
1178
 
 
1179
/*******************************************************************
 
1180
  case insensitive string compararison, length limited
 
1181
********************************************************************/
 
1182
int StrnCaseCmp(char *s, char *t, int n)
 
1183
{
 
1184
  while (n-- && *s && *t) {
 
1185
    if (tolower(*s) != tolower(*t)) return(tolower(*s) - tolower(*t));
 
1186
    s++; t++;
 
1187
  }
 
1188
  if (n) return(tolower(*s) - tolower(*t));
 
1189
 
 
1190
  return(0);
 
1191
}
 
1192
 
 
1193
/*******************************************************************
 
1194
  compare 2 strings 
 
1195
********************************************************************/
 
1196
BOOL strequal(char *s1,char *s2)
 
1197
{
 
1198
  if (!s1 || !s2) return(False);
 
1199
  
 
1200
  return(StrCaseCmp(s1,s2)==0);
 
1201
}
 
1202
 
 
1203
/*******************************************************************
 
1204
  compare 2 strings up to and including the nth char.
 
1205
  ******************************************************************/
 
1206
BOOL strnequal(char *s1,char *s2,int n)
 
1207
{
 
1208
  if (!s1 || !s2 || !n) return(False);
 
1209
  
 
1210
  return(StrnCaseCmp(s1,s2,n)==0);
 
1211
}
 
1212
 
 
1213
/*******************************************************************
 
1214
  compare 2 strings (case sensitive)
 
1215
********************************************************************/
 
1216
BOOL strcsequal(char *s1,char *s2)
 
1217
{
 
1218
  if (!s1 || !s2) return(False);
 
1219
  
 
1220
  return(strcmp(s1,s2)==0);
 
1221
}
 
1222
 
 
1223
#ifdef SCANNER_NOT
 
1224
/* work around fucking BROKEN bfd libraries */
 
1225
/* XXX: it was later found that calling charset_initialise fixed it */
 
1226
void strlower (char * s)
 
1227
{
 
1228
  register unsigned int c;
 
1229
 
 
1230
  while (*s) {
 
1231
    c = (unsigned int) *s;
 
1232
    if (isupper (c))
 
1233
      *s = tolower (c);
 
1234
    s++;
 
1235
  }
 
1236
} /* strlower */
 
1237
void strupper (char * s)
 
1238
{
 
1239
  register unsigned int c;
 
1240
 
 
1241
  while (*s) {
 
1242
    c = (unsigned int) *s;
 
1243
    if (islower (c))
 
1244
      *s = toupper (c);
 
1245
    s++;
 
1246
  }
 
1247
} /* strupper */
 
1248
#else /* SCANNER */
 
1249
 
 
1250
/*******************************************************************
 
1251
  convert a string to lower case
 
1252
********************************************************************/
 
1253
void strlower(char *s)
 
1254
{
 
1255
  while (*s)
 
1256
    {
 
1257
#ifdef KANJI
 
1258
        if (is_shift_jis (*s)) {
 
1259
            s += 2;
 
1260
        } else if (is_kana (*s)) {
 
1261
            s++;
 
1262
        } else {
 
1263
            if (isupper(*s))
 
1264
                *s = tolower(*s);
 
1265
            s++;
 
1266
        }
 
1267
#else
 
1268
      if (isupper(*s))
 
1269
          *s = tolower(*s);
 
1270
      s++;
 
1271
#endif /* KANJI */
 
1272
    }
 
1273
}
 
1274
 
 
1275
/*******************************************************************
 
1276
  convert a string to upper case
 
1277
********************************************************************/
 
1278
void strupper(char *s)
 
1279
{
 
1280
  while (*s)
 
1281
    {
 
1282
#ifdef KANJI
 
1283
        if (is_shift_jis (*s)) {
 
1284
            s += 2;
 
1285
        } else if (is_kana (*s)) {
 
1286
            s++;
 
1287
        } else {
 
1288
            if (islower(*s))
 
1289
                *s = toupper(*s);
 
1290
            s++;
 
1291
        }
 
1292
#else
 
1293
      if (islower(*s))
 
1294
        *s = toupper(*s);
 
1295
      s++;
 
1296
#endif
 
1297
    }
 
1298
}
 
1299
#endif /* SCANNER */
 
1300
 
 
1301
/*******************************************************************
 
1302
  convert a string to "normal" form
 
1303
********************************************************************/
 
1304
void strnorm(char *s)
 
1305
{
 
1306
  if (case_default == CASE_UPPER)
 
1307
    strupper(s);
 
1308
  else
 
1309
    strlower(s);
 
1310
}
 
1311
 
 
1312
/*******************************************************************
 
1313
check if a string is in "normal" case
 
1314
********************************************************************/
 
1315
BOOL strisnormal(char *s)
 
1316
{
 
1317
  if (case_default == CASE_UPPER)
 
1318
    return(!strhaslower(s));
 
1319
 
 
1320
  return(!strhasupper(s));
 
1321
}
 
1322
 
 
1323
 
 
1324
/****************************************************************************
 
1325
  string replace
 
1326
****************************************************************************/
 
1327
void string_replace(char *s,char oldc,char newc)
 
1328
{
 
1329
  while (*s)
 
1330
    {
 
1331
#ifdef KANJI
 
1332
        if (is_shift_jis (*s)) {
 
1333
            s += 2;
 
1334
        } else if (is_kana (*s)) {
 
1335
            s++;
 
1336
        } else {
 
1337
            if (oldc == *s)
 
1338
                *s = newc;
 
1339
            s++;
 
1340
        }
 
1341
#else
 
1342
      if (oldc == *s)
 
1343
        *s = newc;
 
1344
      s++;
 
1345
#endif /* KANJI */
 
1346
    }
 
1347
}
 
1348
 
 
1349
#ifndef SCANNER
 
1350
/****************************************************************************
 
1351
  make a file into unix format
 
1352
****************************************************************************/
 
1353
void unix_format(char *fname)
 
1354
{
 
1355
  pstring namecopy;
 
1356
  string_replace(fname,'\\','/');
 
1357
#ifndef KANJI
 
1358
  dos2unix_format(fname, True);
 
1359
#endif /* KANJI */
 
1360
 
 
1361
  if (*fname == '/')
 
1362
    {
 
1363
      strcpy(namecopy,fname);
 
1364
      strcpy(fname,".");
 
1365
      strcat(fname,namecopy);
 
1366
    }  
 
1367
}
 
1368
 
 
1369
/****************************************************************************
 
1370
  make a file into dos format
 
1371
****************************************************************************/
 
1372
void dos_format(char *fname)
 
1373
{
 
1374
#ifndef KANJI
 
1375
  unix2dos_format(fname, True);
 
1376
#endif /* KANJI */
 
1377
  string_replace(fname,'/','\\');
 
1378
}
 
1379
#endif /* SCANNER */
 
1380
 
 
1381
/*******************************************************************
 
1382
  show a smb message structure
 
1383
********************************************************************/
 
1384
void show_msg(char *buf)
 
1385
{
 
1386
  int i;
 
1387
  int bcc=0;
 
1388
  if (DEBUGLEVEL < 5)
 
1389
    return;
 
1390
 
 
1391
  DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
 
1392
          smb_len(buf),
 
1393
          (int)CVAL(buf,smb_com),
 
1394
          (int)CVAL(buf,smb_rcls),
 
1395
          (int)CVAL(buf,smb_reh),
 
1396
          (int)SVAL(buf,smb_err),
 
1397
          (int)CVAL(buf,smb_flg),
 
1398
          (int)SVAL(buf,smb_flg2)));
 
1399
  DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
 
1400
          (int)SVAL(buf,smb_tid),
 
1401
          (int)SVAL(buf,smb_pid),
 
1402
          (int)SVAL(buf,smb_uid),
 
1403
          (int)SVAL(buf,smb_mid),
 
1404
          (int)CVAL(buf,smb_wct)));
 
1405
  for (i=0;i<(int)CVAL(buf,smb_wct);i++)
 
1406
    DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
 
1407
          SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
 
1408
  bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
 
1409
  DEBUG(5,("smb_bcc=%d\n",bcc));
 
1410
  if (DEBUGLEVEL < 10)
 
1411
    return;
 
1412
  for (i=0;i<MIN(bcc,128);i++)
 
1413
    DEBUG(10,("%X ",CVAL(smb_buf(buf),i)));
 
1414
  DEBUG(10,("\n"));  
 
1415
}
 
1416
 
 
1417
/*******************************************************************
 
1418
  return the length of an smb packet
 
1419
********************************************************************/
 
1420
int smb_len(char *buf)
 
1421
{
 
1422
  return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
 
1423
}
 
1424
 
 
1425
/*******************************************************************
 
1426
  set the length of an smb packet
 
1427
********************************************************************/
 
1428
void _smb_setlen(char *buf,int len)
 
1429
{
 
1430
  buf[0] = 0;
 
1431
  buf[1] = (len&0x10000)>>16;
 
1432
  buf[2] = (len&0xFF00)>>8;
 
1433
  buf[3] = len&0xFF;
 
1434
}
 
1435
 
 
1436
/*******************************************************************
 
1437
  set the length and marker of an smb packet
 
1438
********************************************************************/
 
1439
void smb_setlen(char *buf,int len)
 
1440
{
 
1441
  _smb_setlen(buf,len);
 
1442
 
 
1443
  CVAL(buf,4) = 0xFF;
 
1444
  CVAL(buf,5) = 'S';
 
1445
  CVAL(buf,6) = 'M';
 
1446
  CVAL(buf,7) = 'B';
 
1447
}
 
1448
 
 
1449
/*******************************************************************
 
1450
  setup the word count and byte count for a smb message
 
1451
********************************************************************/
 
1452
int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
 
1453
{
 
1454
  if (zero)
 
1455
    bzero(buf + smb_size,num_words*2 + num_bytes);
 
1456
  CVAL(buf,smb_wct) = num_words;
 
1457
  SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);  
 
1458
  smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
 
1459
  return (smb_size + num_words*2 + num_bytes);
 
1460
}
 
1461
 
 
1462
/*******************************************************************
 
1463
return the number of smb words
 
1464
********************************************************************/
 
1465
int smb_numwords(char *buf)
 
1466
{
 
1467
  return (CVAL(buf,smb_wct));
 
1468
}
 
1469
 
 
1470
/*******************************************************************
 
1471
return the size of the smb_buf region of a message
 
1472
********************************************************************/
 
1473
int smb_buflen(char *buf)
 
1474
{
 
1475
  return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
 
1476
}
 
1477
 
 
1478
/*******************************************************************
 
1479
  return a pointer to the smb_buf data area
 
1480
********************************************************************/
 
1481
int smb_buf_ofs(char *buf)
 
1482
{
 
1483
  return (smb_size + CVAL(buf,smb_wct)*2);
 
1484
}
 
1485
 
 
1486
/*******************************************************************
 
1487
  return a pointer to the smb_buf data area
 
1488
********************************************************************/
 
1489
char *smb_buf(char *buf)
 
1490
{
 
1491
  return (buf + smb_buf_ofs(buf));
 
1492
}
 
1493
 
 
1494
/*******************************************************************
 
1495
return the SMB offset into an SMB buffer
 
1496
********************************************************************/
 
1497
int smb_offset(char *p,char *buf)
 
1498
{
 
1499
  return(PTR_DIFF(p,buf+4));
 
1500
}
 
1501
 
 
1502
 
 
1503
/*******************************************************************
 
1504
skip past some strings in a buffer
 
1505
********************************************************************/
 
1506
char *skip_string(char *buf,int n)
 
1507
{
 
1508
  while (n--)
 
1509
    buf += strlen(buf) + 1;
 
1510
  return(buf);
 
1511
}
 
1512
 
 
1513
/*******************************************************************
 
1514
trim the specified elements off the front and back of a string
 
1515
********************************************************************/
 
1516
BOOL trim_string(char *s,char *front,char *back)
 
1517
{
 
1518
  BOOL ret = False;
 
1519
  while (front && *front && strncmp(s,front,strlen(front)) == 0)
 
1520
    {
 
1521
      char *p = s;
 
1522
      ret = True;
 
1523
      while (1)
 
1524
        {
 
1525
          if (!(*p = p[strlen(front)]))
 
1526
            break;
 
1527
          p++;
 
1528
        }
 
1529
    }
 
1530
  while (back && *back && strlen(s) >= strlen(back) && 
 
1531
         (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))  
 
1532
    {
 
1533
      ret = True;
 
1534
      s[strlen(s)-strlen(back)] = 0;
 
1535
    }
 
1536
  return(ret);
 
1537
}
 
1538
 
 
1539
 
 
1540
/*******************************************************************
 
1541
reduce a file name, removing .. elements.
 
1542
********************************************************************/
 
1543
void dos_clean_name(char *s)
 
1544
{
 
1545
  char *p=NULL;
 
1546
 
 
1547
  DEBUG(3,("dos_clean_name [%s]\n",s));
 
1548
 
 
1549
  /* remove any double slashes */
 
1550
  string_sub(s, "\\\\", "\\");
 
1551
 
 
1552
  while ((p = strstr(s,"\\..\\")) != NULL)
 
1553
    {
 
1554
      pstring s1;
 
1555
 
 
1556
      *p = 0;
 
1557
      strcpy(s1,p+3);
 
1558
 
 
1559
      if ((p=strrchr(s,'\\')) != NULL)
 
1560
        *p = 0;
 
1561
      else
 
1562
        *s = 0;
 
1563
      strcat(s,s1);
 
1564
    }  
 
1565
 
 
1566
  trim_string(s,NULL,"\\..");
 
1567
 
 
1568
  string_sub(s, "\\.\\", "\\");
 
1569
}
 
1570
 
 
1571
/*******************************************************************
 
1572
reduce a file name, removing .. elements. 
 
1573
********************************************************************/
 
1574
void unix_clean_name(char *s)
 
1575
{
 
1576
  char *p=NULL;
 
1577
 
 
1578
  DEBUG(3,("unix_clean_name [%s]\n",s));
 
1579
 
 
1580
  /* remove any double slashes */
 
1581
  string_sub(s, "//","/");
 
1582
 
 
1583
  while ((p = strstr(s,"/../")) != NULL)
 
1584
    {
 
1585
      pstring s1;
 
1586
 
 
1587
      *p = 0;
 
1588
      strcpy(s1,p+3);
 
1589
 
 
1590
      if ((p=strrchr(s,'/')) != NULL)
 
1591
        *p = 0;
 
1592
      else
 
1593
        *s = 0;
 
1594
      strcat(s,s1);
 
1595
    }  
 
1596
 
 
1597
  trim_string(s,NULL,"/..");
 
1598
}
 
1599
 
 
1600
 
 
1601
/*******************************************************************
 
1602
a wrapper for the normal chdir() function
 
1603
********************************************************************/
 
1604
int ChDir(char *path)
 
1605
{
 
1606
  int res;
 
1607
  static pstring LastDir="";
 
1608
 
 
1609
  if (strcsequal(path,".")) return(0);
 
1610
 
 
1611
  if (*path == '/' && strcsequal(LastDir,path)) return(0);
 
1612
  DEBUG(3,("chdir to %s\n",path));
 
1613
  res = sys_chdir(path);
 
1614
  if (!res)
 
1615
    strcpy(LastDir,path);
 
1616
  return(res);
 
1617
}
 
1618
 
 
1619
 
 
1620
/*******************************************************************
 
1621
  return the absolute current directory path. A dumb version.
 
1622
********************************************************************/
 
1623
static char *Dumb_GetWd(char *s)
 
1624
{
 
1625
#ifdef USE_GETCWD
 
1626
    return ((char *)getcwd(s,sizeof(pstring)));
 
1627
#else
 
1628
    return ((char *)getwd(s));
 
1629
#endif
 
1630
}
 
1631
 
 
1632
 
 
1633
/* number of list structures for a caching GetWd function. */
 
1634
#define MAX_GETWDCACHE (50)
 
1635
 
 
1636
struct
 
1637
{
 
1638
  ino_t inode;
 
1639
  dev_t dev;
 
1640
  char *text;
 
1641
  BOOL valid;
 
1642
} ino_list[MAX_GETWDCACHE];
 
1643
 
 
1644
BOOL use_getwd_cache=True;
 
1645
 
 
1646
/*******************************************************************
 
1647
  return the absolute current directory path
 
1648
********************************************************************/
 
1649
char *GetWd(char *str)
 
1650
{
 
1651
  pstring s;
 
1652
  static BOOL getwd_cache_init = False;
 
1653
  struct stat st, st2;
 
1654
  int i;
 
1655
 
 
1656
  *s = 0;
 
1657
 
 
1658
  if (!use_getwd_cache)
 
1659
    return(Dumb_GetWd(str));
 
1660
 
 
1661
  /* init the cache */
 
1662
  if (!getwd_cache_init)
 
1663
    {
 
1664
      getwd_cache_init = True;
 
1665
      for (i=0;i<MAX_GETWDCACHE;i++)
 
1666
        {
 
1667
          string_init(&ino_list[i].text,"");
 
1668
          ino_list[i].valid = False;
 
1669
        }
 
1670
    }
 
1671
 
 
1672
  /*  Get the inode of the current directory, if this doesn't work we're
 
1673
      in trouble :-) */
 
1674
 
 
1675
  if (stat(".",&st) == -1) 
 
1676
    {
 
1677
      DEBUG(0,("Very strange, couldn't stat \".\"\n"));
 
1678
      return(Dumb_GetWd(str));
 
1679
    }
 
1680
 
 
1681
 
 
1682
  for (i=0; i<MAX_GETWDCACHE; i++)
 
1683
    if (ino_list[i].valid)
 
1684
      {
 
1685
 
 
1686
        /*  If we have found an entry with a matching inode and dev number
 
1687
            then find the inode number for the directory in the cached string.
 
1688
            If this agrees with that returned by the stat for the current
 
1689
            directory then all is o.k. (but make sure it is a directory all
 
1690
            the same...) */
 
1691
      
 
1692
        if (st.st_ino == ino_list[i].inode &&
 
1693
            st.st_dev == ino_list[i].dev)
 
1694
          {
 
1695
            if (stat(ino_list[i].text,&st2) == 0)
 
1696
              {
 
1697
                if (st.st_ino == st2.st_ino &&
 
1698
                    st.st_dev == st2.st_dev &&
 
1699
                    (st2.st_mode & S_IFMT) == S_IFDIR)
 
1700
                  {
 
1701
                    strcpy (str, ino_list[i].text);
 
1702
 
 
1703
                    /* promote it for future use */
 
1704
                    array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
 
1705
                    return (str);
 
1706
                  }
 
1707
                else
 
1708
                  {
 
1709
                    /*  If the inode is different then something's changed, 
 
1710
                        scrub the entry and start from scratch. */
 
1711
                    ino_list[i].valid = False;
 
1712
                  }
 
1713
              }
 
1714
          }
 
1715
      }
 
1716
 
 
1717
 
 
1718
  /*  We don't have the information to hand so rely on traditional methods.
 
1719
      The very slow getcwd, which spawns a process on some systems, or the
 
1720
      not quite so bad getwd. */
 
1721
 
 
1722
  if (!Dumb_GetWd(s))
 
1723
    {
 
1724
      DEBUG(0,("Getwd failed, errno %d\n",errno));
 
1725
      return (NULL);
 
1726
    }
 
1727
 
 
1728
  strcpy(str,s);
 
1729
 
 
1730
  DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
 
1731
 
 
1732
  /* add it to the cache */
 
1733
  i = MAX_GETWDCACHE - 1;
 
1734
  string_set(&ino_list[i].text,s);
 
1735
  ino_list[i].dev = st.st_dev;
 
1736
  ino_list[i].inode = st.st_ino;
 
1737
  ino_list[i].valid = True;
 
1738
 
 
1739
  /* put it at the top of the list */
 
1740
  array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
 
1741
 
 
1742
  return (str);
 
1743
}
 
1744
 
 
1745
 
 
1746
 
 
1747
/*******************************************************************
 
1748
reduce a file name, removing .. elements and checking that 
 
1749
it is below dir in the heirachy. This uses GetWd() and so must be run
 
1750
on the system that has the referenced file system.
 
1751
 
 
1752
widelinks are allowed if widelinks is true
 
1753
********************************************************************/
 
1754
BOOL reduce_name(char *s,char *dir,BOOL widelinks)
 
1755
{
 
1756
#ifndef REDUCE_PATHS
 
1757
  return True;
 
1758
#else
 
1759
  pstring dir2;
 
1760
  pstring wd;
 
1761
  pstring basename;
 
1762
  pstring newname;
 
1763
  char *p=NULL;
 
1764
  BOOL relative = (*s != '/');
 
1765
 
 
1766
  *dir2 = *wd = *basename = *newname = 0;
 
1767
 
 
1768
  if (widelinks)
 
1769
    {
 
1770
      unix_clean_name(s);
 
1771
      /* can't have a leading .. */
 
1772
      if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
 
1773
        {
 
1774
          DEBUG(3,("Illegal file name? (%s)\n",s));
 
1775
          return(False);
 
1776
        }
 
1777
      return(True);
 
1778
    }
 
1779
  
 
1780
  DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
 
1781
 
 
1782
  /* remove any double slashes */
 
1783
  string_sub(s,"//","/");
 
1784
 
 
1785
  strcpy(basename,s);
 
1786
  p = strrchr(basename,'/');
 
1787
 
 
1788
  if (!p)
 
1789
    return(True);
 
1790
 
 
1791
  if (!GetWd(wd))
 
1792
    {
 
1793
      DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
 
1794
      return(False);
 
1795
    }
 
1796
 
 
1797
  if (ChDir(dir) != 0)
 
1798
    {
 
1799
      DEBUG(0,("couldn't chdir to %s\n",dir));
 
1800
      return(False);
 
1801
    }
 
1802
 
 
1803
  if (!GetWd(dir2))
 
1804
    {
 
1805
      DEBUG(0,("couldn't getwd for %s\n",dir));
 
1806
      ChDir(wd);
 
1807
      return(False);
 
1808
    }
 
1809
 
 
1810
 
 
1811
    if (p && (p != basename))
 
1812
      {
 
1813
        *p = 0;
 
1814
        if (strcmp(p+1,".")==0)
 
1815
          p[1]=0;
 
1816
        if (strcmp(p+1,"..")==0)
 
1817
          *p = '/';
 
1818
      }
 
1819
 
 
1820
  if (ChDir(basename) != 0)
 
1821
    {
 
1822
      ChDir(wd);
 
1823
      DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
 
1824
      return(False);
 
1825
    }
 
1826
 
 
1827
  if (!GetWd(newname))
 
1828
    {
 
1829
      ChDir(wd);
 
1830
      DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
 
1831
      return(False);
 
1832
    }
 
1833
 
 
1834
  if (p && (p != basename))
 
1835
    {
 
1836
      strcat(newname,"/");
 
1837
      strcat(newname,p+1);
 
1838
    }
 
1839
 
 
1840
  {
 
1841
    int l = strlen(dir2);    
 
1842
    if (dir2[l-1] == '/')
 
1843
      l--;
 
1844
 
 
1845
    if (strncmp(newname,dir2,l) != 0)
 
1846
      {
 
1847
        ChDir(wd);
 
1848
        DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
 
1849
        return(False);
 
1850
      }
 
1851
 
 
1852
    if (relative)
 
1853
      {
 
1854
        if (newname[l] == '/')
 
1855
          strcpy(s,newname + l + 1);
 
1856
        else
 
1857
          strcpy(s,newname+l);
 
1858
      }
 
1859
    else
 
1860
      strcpy(s,newname);
 
1861
  }
 
1862
 
 
1863
  ChDir(wd);
 
1864
 
 
1865
  if (strlen(s) == 0)
 
1866
    strcpy(s,"./");
 
1867
 
 
1868
  DEBUG(3,("reduced to %s\n",s));
 
1869
  return(True);
 
1870
#endif
 
1871
}
 
1872
 
 
1873
/****************************************************************************
 
1874
expand some *s 
 
1875
****************************************************************************/
 
1876
static void expand_one(char *Mask,int len)
 
1877
{
 
1878
  char *p1;
 
1879
  while ((p1 = strchr(Mask,'*')) != NULL)
 
1880
    {
 
1881
      int lfill = (len+1) - strlen(Mask);
 
1882
      int l1= (p1 - Mask);
 
1883
      pstring tmp;
 
1884
      strcpy(tmp,Mask);  
 
1885
      memset(tmp+l1,'?',lfill);
 
1886
      strcpy(tmp + l1 + lfill,Mask + l1 + 1);   
 
1887
      strcpy(Mask,tmp);      
 
1888
    }
 
1889
}
 
1890
 
 
1891
/****************************************************************************
 
1892
expand a wildcard expression, replacing *s with ?s
 
1893
****************************************************************************/
 
1894
void expand_mask(char *Mask,BOOL doext)
 
1895
{
 
1896
  pstring mbeg,mext;
 
1897
  pstring dirpart;
 
1898
  pstring filepart;
 
1899
  BOOL hasdot = False;
 
1900
  char *p1;
 
1901
  BOOL absolute = (*Mask == '\\');
 
1902
 
 
1903
  *mbeg = *mext = *dirpart = *filepart = 0;
 
1904
 
 
1905
  /* parse the directory and filename */
 
1906
  if (strchr(Mask,'\\'))
 
1907
    dirname_dos(Mask,dirpart);
 
1908
 
 
1909
  filename_dos(Mask,filepart);
 
1910
 
 
1911
  strcpy(mbeg,filepart);
 
1912
  if ((p1 = strchr(mbeg,'.')) != NULL)
 
1913
    {
 
1914
      hasdot = True;
 
1915
      *p1 = 0;
 
1916
      p1++;
 
1917
      strcpy(mext,p1);
 
1918
    }
 
1919
  else
 
1920
    {
 
1921
      strcpy(mext,"");
 
1922
      if (strlen(mbeg) > 8)
 
1923
        {
 
1924
          strcpy(mext,mbeg + 8);
 
1925
          mbeg[8] = 0;
 
1926
        }
 
1927
    }
 
1928
 
 
1929
  if (*mbeg == 0)
 
1930
    strcpy(mbeg,"????????");
 
1931
  if ((*mext == 0) && doext && !hasdot)
 
1932
    strcpy(mext,"???");
 
1933
 
 
1934
  /* expand *'s */
 
1935
  expand_one(mbeg,8);
 
1936
  if (*mext)
 
1937
    expand_one(mext,3);
 
1938
 
 
1939
  strcpy(Mask,dirpart);
 
1940
  if (*dirpart || absolute) strcat(Mask,"\\");
 
1941
  strcat(Mask,mbeg);
 
1942
  strcat(Mask,".");
 
1943
  strcat(Mask,mext);
 
1944
 
 
1945
  DEBUG(6,("Mask expanded to [%s]\n",Mask));
 
1946
}  
 
1947
 
 
1948
 
 
1949
/****************************************************************************
 
1950
does a string have any uppercase chars in it?
 
1951
****************************************************************************/
 
1952
BOOL strhasupper(char *s)
 
1953
{
 
1954
  while (*s) 
 
1955
    {
 
1956
#ifdef KANJI
 
1957
        if (is_shift_jis (*s)) {
 
1958
            s += 2;
 
1959
        } else if (is_kana (*s)) {
 
1960
            s++;
 
1961
        } else {
 
1962
            if (isupper(*s)) return(True);
 
1963
            s++;
 
1964
        }
 
1965
#else 
 
1966
      if (isupper(*s)) return(True);
 
1967
      s++;
 
1968
#endif /* KANJI */
 
1969
    }
 
1970
  return(False);
 
1971
}
 
1972
 
 
1973
/****************************************************************************
 
1974
does a string have any lowercase chars in it?
 
1975
****************************************************************************/
 
1976
BOOL strhaslower(char *s)
 
1977
{
 
1978
  while (*s) 
 
1979
    {
 
1980
#ifdef KANJI
 
1981
        if (is_shift_jis (*s)) {
 
1982
            s += 2;
 
1983
        } else if (is_kana (*s)) {
 
1984
            s++;
 
1985
        } else {
 
1986
            if (islower(*s)) return(True);
 
1987
            s++;
 
1988
        }
 
1989
#else 
 
1990
      if (islower(*s)) return(True);
 
1991
      s++;
 
1992
#endif /* KANJI */
 
1993
    }
 
1994
  return(False);
 
1995
}
 
1996
 
 
1997
/****************************************************************************
 
1998
find the number of chars in a string
 
1999
****************************************************************************/
 
2000
int count_chars(char *s,char c)
 
2001
{
 
2002
  int count=0;
 
2003
  while (*s) 
 
2004
    {
 
2005
      if (*s == c)
 
2006
        count++;
 
2007
      s++;
 
2008
    }
 
2009
  return(count);
 
2010
}
 
2011
 
 
2012
 
 
2013
/****************************************************************************
 
2014
  make a dir struct
 
2015
****************************************************************************/
 
2016
void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
 
2017
{  
 
2018
  char *p;
 
2019
  pstring mask2;
 
2020
 
 
2021
  strcpy(mask2,mask);
 
2022
 
 
2023
  if ((mode & aDIR) != 0)
 
2024
    size = 0;
 
2025
 
 
2026
  memset(buf+1,' ',11);
 
2027
  if ((p = strchr(mask2,'.')) != NULL)
 
2028
    {
 
2029
      *p = 0;
 
2030
      memcpy(buf+1,mask2,MIN(strlen(mask2),8));
 
2031
      memcpy(buf+9,p+1,MIN(strlen(p+1),3));
 
2032
      *p = '.';
 
2033
    }
 
2034
  else
 
2035
    memcpy(buf+1,mask2,MIN(strlen(mask2),11));
 
2036
 
 
2037
  bzero(buf+21,DIR_STRUCT_SIZE-21);
 
2038
  CVAL(buf,21) = mode;
 
2039
  put_dos_date(buf,22,date);
 
2040
  SSVAL(buf,26,size & 0xFFFF);
 
2041
  SSVAL(buf,28,size >> 16);
 
2042
  StrnCpy(buf+30,fname,12);
 
2043
  if (!case_sensitive)
 
2044
    strupper(buf+30);
 
2045
  DEBUG(8,("put name [%s] into dir struct\n",buf+30));
 
2046
}
 
2047
 
 
2048
 
 
2049
/*******************************************************************
 
2050
close the low 3 fd's and open dev/null in their place
 
2051
********************************************************************/
 
2052
void close_low_fds(void)
 
2053
{
 
2054
  int fd;
 
2055
  int i;
 
2056
  close(0); close(1); close(2);
 
2057
  /* try and use up these file descriptors, so silly
 
2058
     library routines writing to stdout etc won't cause havoc */
 
2059
  for (i=0;i<3;i++) {
 
2060
    fd = open("/dev/null",O_RDWR,0);
 
2061
    if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
 
2062
    if (fd < 0) {
 
2063
      DEBUG(0,("Can't open /dev/null\n"));
 
2064
      return;
 
2065
    }
 
2066
    if (fd != i) {
 
2067
      DEBUG(0,("Didn't get file descriptor %d\n",i));
 
2068
      return;
 
2069
    }
 
2070
  }
 
2071
}
 
2072
 
 
2073
 
 
2074
/****************************************************************************
 
2075
write to a socket
 
2076
****************************************************************************/
 
2077
int write_socket(int fd,char *buf,int len)
 
2078
{
 
2079
  int ret=0;
 
2080
 
 
2081
  if (passive)
 
2082
    return(len);
 
2083
  DEBUG(6,("write_socket(%d,%d)\n",fd,len));
 
2084
  ret = write_data(fd,buf,len);
 
2085
      
 
2086
  DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
 
2087
  return(ret);
 
2088
}
 
2089
 
 
2090
/****************************************************************************
 
2091
read from a socket
 
2092
****************************************************************************/
 
2093
int read_udp_socket(int fd,char *buf,int len)
 
2094
{
 
2095
  int ret;
 
2096
  struct sockaddr sock;
 
2097
  int socklen;
 
2098
  
 
2099
  socklen = sizeof(sock);
 
2100
  bzero((char *)&sock,socklen);
 
2101
  bzero((char *)&lastip,sizeof(lastip));
 
2102
  ret = recvfrom(fd,buf,len,0,&sock,&socklen);
 
2103
  if (ret <= 0)
 
2104
    {
 
2105
      DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
 
2106
      return(0);
 
2107
    }
 
2108
 
 
2109
  lastip = *(struct in_addr *) &sock.sa_data[2];
 
2110
  lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
 
2111
 
 
2112
  return(ret);
 
2113
}
 
2114
 
 
2115
/****************************************************************************
 
2116
Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
 
2117
else
 
2118
if SYSV use O_NDELAY
 
2119
if BSD use FNDELAY
 
2120
****************************************************************************/
 
2121
int set_blocking(int fd, BOOL set)
 
2122
{
 
2123
int val;
 
2124
#ifdef O_NONBLOCK
 
2125
#define FLAG_TO_SET O_NONBLOCK
 
2126
#else
 
2127
#ifdef SYSV
 
2128
#define FLAG_TO_SET O_NDELAY
 
2129
#else /* BSD */
 
2130
#define FLAG_TO_SET FNDELAY
 
2131
#endif
 
2132
#endif
 
2133
 
 
2134
  if((val = fcntl(fd, F_GETFL, 0))==-1)
 
2135
        return -1;
 
2136
  if(set) /* Turn blocking on - ie. clear nonblock flag */
 
2137
        val &= ~FLAG_TO_SET;
 
2138
  else
 
2139
    val |= FLAG_TO_SET;
 
2140
  return fcntl( fd, F_SETFL, val);
 
2141
#undef FLAG_TO_SET
 
2142
}
 
2143
 
 
2144
 
 
2145
/****************************************************************************
 
2146
Calculate the difference in timeout values. Return 1 if val1 > val2,
 
2147
0 if val1 == val2, -1 if val1 < val2. Stores result in retval. retval
 
2148
may be == val1 or val2
 
2149
****************************************************************************/
 
2150
static int tval_sub( struct timeval *retval, struct timeval *val1, struct timeval *val2)
 
2151
{
 
2152
  int usecdiff = val1->tv_usec - val2->tv_usec;
 
2153
  int secdiff = val1->tv_sec - val2->tv_sec;
 
2154
  if(usecdiff < 0) {
 
2155
    usecdiff = 1000000 + usecdiff;
 
2156
    secdiff--;
 
2157
  }
 
2158
  retval->tv_sec = secdiff;
 
2159
  retval->tv_usec = usecdiff;
 
2160
  if(secdiff < 0)
 
2161
    return -1;
 
2162
  if(secdiff > 0)
 
2163
    return 1;
 
2164
  return (usecdiff < 0 ) ? -1 : ((usecdiff > 0 ) ? 1 : 0);
 
2165
}
 
2166
 
 
2167
/****************************************************************************
 
2168
read data from a device with a timout in msec.
 
2169
mincount = if timeout, minimum to read before returning
 
2170
maxcount = number to be read.
 
2171
****************************************************************************/
 
2172
int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out,BOOL exact)
 
2173
{
 
2174
  fd_set fds;
 
2175
  int selrtn;
 
2176
  int readret;
 
2177
  int nread = 0;
 
2178
  struct timeval timeout, tval1, tval2, tvaldiff;
 
2179
 
 
2180
  /* just checking .... */
 
2181
  if (maxcnt <= 0) return(0);
 
2182
 
 
2183
  if(time_out == -2)
 
2184
    time_out = DEFAULT_PIPE_TIMEOUT;
 
2185
 
 
2186
  /* Blocking read */
 
2187
  if(time_out < 0) {
 
2188
    if (mincnt == 0) mincnt = maxcnt;
 
2189
 
 
2190
    while (nread < mincnt)
 
2191
      {
 
2192
        readret = read(fd, buf + nread, maxcnt - nread);
 
2193
        if (readret <= 0) return(nread);
 
2194
        nread += readret;
 
2195
      }
 
2196
    return(nread);
 
2197
  }
 
2198
  
 
2199
  /* Non blocking read */
 
2200
  if(time_out == 0) {
 
2201
    set_blocking(fd, False);
 
2202
    nread = read_data(fd, buf, mincnt);
 
2203
    if (nread < maxcnt)
 
2204
      nread += read(fd,buf+nread,maxcnt-nread);
 
2205
    if(nread == -1 && errno == EWOULDBLOCK)
 
2206
      nread = 0;
 
2207
    set_blocking(fd,True);
 
2208
    return nread;
 
2209
  }
 
2210
 
 
2211
  /* Most difficult - timeout read */
 
2212
  /* If this is ever called on a disk file and 
 
2213
         mincnt is greater then the filesize then
 
2214
         system performance will suffer severely as 
 
2215
         select always return true on disk files */
 
2216
 
 
2217
  /* Set initial timeout */
 
2218
  timeout.tv_sec = time_out / 1000;
 
2219
  timeout.tv_usec = 1000 * (time_out % 1000);
 
2220
 
 
2221
  /* As most UNIXes don't modify the value of timeout
 
2222
     when they return from select we need to get the timeofday (in usec)
 
2223
     now, and also after the select returns so we know
 
2224
     how much time has elapsed */
 
2225
 
 
2226
  if (exact)
 
2227
    GetTimeOfDay( &tval1);
 
2228
  nread = 0; /* Number of bytes we have read */
 
2229
 
 
2230
  for(;;) 
 
2231
    {
 
2232
      
 
2233
      FD_ZERO(&fds);
 
2234
      FD_SET(fd,&fds);
 
2235
      
 
2236
      selrtn = sys_select(&fds,&timeout);
 
2237
      
 
2238
      /* Check if error */
 
2239
      if(selrtn == -1)
 
2240
        {
 
2241
          errno = EBADF;
 
2242
          return -1;
 
2243
        }
 
2244
      
 
2245
      /* Did we timeout ? */
 
2246
      if (selrtn == 0 ) {
 
2247
         if (nread < mincnt) return -1;
 
2248
        break; /* Yes */
 
2249
      }
 
2250
      
 
2251
      readret = read( fd, buf+nread, maxcnt-nread);
 
2252
      if(readret <= 0)
 
2253
        {
 
2254
          /* force a particular error number for
 
2255
             portability */
 
2256
          errno = EBADF;
 
2257
          return -1;
 
2258
        }
 
2259
 
 
2260
      if (readret == 0)
 
2261
        break;
 
2262
      
 
2263
      nread += readret;
 
2264
      
 
2265
      /* If we have read more than mincnt then return */
 
2266
      if( nread >= mincnt )
 
2267
        break;
 
2268
 
 
2269
      /* We need to do another select - but first reduce the
 
2270
         time_out by the amount of time already elapsed - if
 
2271
         this is less than zero then return */
 
2272
      if (exact)
 
2273
        {
 
2274
          GetTimeOfDay( &tval2);
 
2275
          (void)tval_sub( &tvaldiff, &tval2, &tval1);
 
2276
      
 
2277
          if( tval_sub( &timeout, &timeout, &tvaldiff) <= 0) 
 
2278
            {
 
2279
              /* We timed out */
 
2280
              break;
 
2281
            }
 
2282
        }
 
2283
      
 
2284
      /* Save the time of day as we need to do the select 
 
2285
         again (saves a system call)*/
 
2286
      tval1 = tval2;
 
2287
    }
 
2288
 
 
2289
  /* Return the number we got */
 
2290
  return(nread);
 
2291
}
 
2292
 
 
2293
/****************************************************************************
 
2294
read data from the client. Maxtime is in milliseconds
 
2295
****************************************************************************/
 
2296
int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
 
2297
{
 
2298
  fd_set fds;
 
2299
  int selrtn;
 
2300
  int nread;
 
2301
  struct timeval timeout;
 
2302
 
 
2303
  FD_ZERO(&fds);
 
2304
  FD_SET(fd,&fds);
 
2305
 
 
2306
  timeout.tv_sec = maxtime / 1000;
 
2307
  timeout.tv_usec = (maxtime % 1000) * 1000;
 
2308
 
 
2309
  selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
 
2310
 
 
2311
  if (!FD_ISSET(fd,&fds))
 
2312
    return 0;
 
2313
 
 
2314
  nread = read_udp_socket(fd, buffer, bufsize);
 
2315
 
 
2316
  /* return the number got */
 
2317
  return(nread);
 
2318
}
 
2319
 
 
2320
/*******************************************************************
 
2321
find the difference in milliseconds between two struct timeval
 
2322
values
 
2323
********************************************************************/
 
2324
int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
 
2325
{
 
2326
  return((tvalnew->tv_sec - tvalold->tv_sec)*1000 + 
 
2327
         ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);  
 
2328
}
 
2329
 
 
2330
/****************************************************************************
 
2331
send a keepalive packet (rfc1002)
 
2332
****************************************************************************/
 
2333
BOOL send_keepalive(int client)
 
2334
{
 
2335
  unsigned char buf[4];
 
2336
 
 
2337
  buf[0] = 0x85;
 
2338
  buf[1] = buf[2] = buf[3] = 0;
 
2339
 
 
2340
  return(write_data(client,(char *)buf,4) == 4);
 
2341
}
 
2342
 
 
2343
 
 
2344
 
 
2345
/****************************************************************************
 
2346
  read data from the client, reading exactly N bytes. 
 
2347
****************************************************************************/
 
2348
int read_data(int fd,char *buffer,int N)
 
2349
{
 
2350
  int  ret;
 
2351
  int total=0;  
 
2352
 
 
2353
  while (total < N)
 
2354
    {
 
2355
      ret = read(fd,buffer + total,N - total);
 
2356
 
 
2357
      /* this is for portability */
 
2358
      if (ret < 0)
 
2359
        errno = EBADF;
 
2360
 
 
2361
      if (ret <= 0)
 
2362
        return total;
 
2363
      total += ret;
 
2364
    }
 
2365
  return total;
 
2366
}
 
2367
 
 
2368
 
 
2369
/****************************************************************************
 
2370
  write data to a fd 
 
2371
****************************************************************************/
 
2372
int write_data(int fd,char *buffer,int N)
 
2373
{
 
2374
  int total=0;
 
2375
  int ret;
 
2376
 
 
2377
  while (total < N)
 
2378
    {
 
2379
      ret = write(fd,buffer + total,N - total);
 
2380
 
 
2381
      if (ret <= 0)
 
2382
        return total;
 
2383
 
 
2384
      total += ret;
 
2385
    }
 
2386
  return total;
 
2387
}
 
2388
 
 
2389
 
 
2390
/* variables used by the read prediction module */
 
2391
int rp_fd = -1;
 
2392
int rp_offset = 0;
 
2393
int rp_length = 0;
 
2394
int rp_alloced = 0;
 
2395
int rp_predict_fd = -1;
 
2396
int rp_predict_offset = 0;
 
2397
int rp_predict_length = 0;
 
2398
int rp_timeout = 5;
 
2399
time_t rp_time = 0;
 
2400
char *rp_buffer = NULL;
 
2401
BOOL predict_skip=False;
 
2402
time_t smb_last_time=(time_t)0;
 
2403
 
 
2404
/****************************************************************************
 
2405
handle read prediction on a file
 
2406
****************************************************************************/
 
2407
int read_predict(int fd,int offset,char *buf,char **ptr,int num)
 
2408
{
 
2409
  int ret = 0;
 
2410
  int possible = rp_length - (offset - rp_offset);
 
2411
 
 
2412
  possible = MIN(possible,num);
 
2413
 
 
2414
  /* give data if possible */
 
2415
  if (fd == rp_fd && 
 
2416
      offset >= rp_offset && 
 
2417
      possible>0 &&
 
2418
      smb_last_time-rp_time < rp_timeout)
 
2419
    {
 
2420
      ret = possible;
 
2421
      if (buf)
 
2422
        memcpy(buf,rp_buffer + (offset-rp_offset),possible);
 
2423
      else
 
2424
        *ptr = rp_buffer + (offset-rp_offset);
 
2425
      DEBUG(5,("read-prediction gave %d bytes of %d\n",ret,num));
 
2426
    }
 
2427
 
 
2428
  if (ret == num) {
 
2429
    predict_skip = True;
 
2430
  } else {
 
2431
    predict_skip = False;
 
2432
 
 
2433
    /* prepare the next prediction */
 
2434
    rp_predict_fd = fd;
 
2435
    rp_predict_offset = offset + num;
 
2436
    rp_predict_length = num;
 
2437
  }
 
2438
 
 
2439
  if (ret < 0) ret = 0;
 
2440
 
 
2441
  return(ret);
 
2442
}
 
2443
 
 
2444
/****************************************************************************
 
2445
pre-read some data
 
2446
****************************************************************************/
 
2447
void do_read_prediction()
 
2448
{
 
2449
  if (predict_skip) return;
 
2450
 
 
2451
  if (rp_predict_fd == -1) 
 
2452
    return;
 
2453
 
 
2454
  rp_fd = rp_predict_fd;
 
2455
  rp_offset = rp_predict_offset;
 
2456
  rp_length = 0;
 
2457
 
 
2458
  rp_predict_fd = -1;
 
2459
 
 
2460
  rp_predict_length = MIN(rp_predict_length,2*ReadSize);
 
2461
  rp_predict_length = MAX(rp_predict_length,1024);
 
2462
  rp_offset = (rp_offset/1024)*1024;
 
2463
  rp_predict_length = (rp_predict_length/1024)*1024;
 
2464
 
 
2465
  if (rp_predict_length > rp_alloced)
 
2466
    {
 
2467
      rp_buffer = Realloc(rp_buffer,rp_predict_length);
 
2468
      rp_alloced = rp_predict_length;
 
2469
      if (!rp_buffer)
 
2470
        {
 
2471
          DEBUG(0,("can't allocate read-prediction buffer\n"));
 
2472
          rp_predict_fd = -1;
 
2473
          rp_fd = -1;
 
2474
          rp_alloced = 0;
 
2475
          return;
 
2476
        }
 
2477
    }
 
2478
 
 
2479
  if (lseek(rp_fd,rp_offset,SEEK_SET) != rp_offset) {
 
2480
    rp_fd = -1;
 
2481
    rp_predict_fd = -1;
 
2482
    return;
 
2483
  }
 
2484
 
 
2485
  rp_length = read(rp_fd,rp_buffer,rp_predict_length);
 
2486
  rp_time = time(NULL);
 
2487
  if (rp_length < 0)
 
2488
    rp_length = 0;
 
2489
}
 
2490
 
 
2491
/****************************************************************************
 
2492
invalidate read-prediction on a fd
 
2493
****************************************************************************/
 
2494
void invalidate_read_prediction(int fd)
 
2495
{
 
2496
 if (rp_fd == fd) 
 
2497
   rp_fd = -1;
 
2498
 if (rp_predict_fd == fd)
 
2499
   rp_predict_fd = -1;
 
2500
}
 
2501
 
 
2502
 
 
2503
/****************************************************************************
 
2504
transfer some data between two fd's
 
2505
****************************************************************************/
 
2506
int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
 
2507
{
 
2508
  static char *buf=NULL;  
 
2509
  char *buf1,*abuf;
 
2510
  static int size = 0;
 
2511
  int total = 0;
 
2512
 
 
2513
  DEBUG(4,("transfer_file %d  (head=%d) called\n",n,headlen));
 
2514
 
 
2515
  if ((size < ReadSize) && buf) {
 
2516
    free(buf);
 
2517
    buf = NULL;
 
2518
  }
 
2519
 
 
2520
  size = MAX(ReadSize,1024);
 
2521
 
 
2522
  while (!buf && size>0) {
 
2523
    buf = (char *)Realloc(buf,size+8);
 
2524
    if (!buf) size /= 2;
 
2525
  }
 
2526
  if (!buf) {
 
2527
    DEBUG(0,("Can't allocate transfer buffer!\n"));
 
2528
    exit(1);
 
2529
  }
 
2530
 
 
2531
  abuf = buf + (align%8);
 
2532
 
 
2533
  if (header)
 
2534
    n += headlen;
 
2535
 
 
2536
  while (n > 0)
 
2537
    {
 
2538
      int s = MIN(n,size);
 
2539
      int ret,ret2=0;
 
2540
 
 
2541
      ret = 0;
 
2542
 
 
2543
      if (header && (headlen >= MIN(s,1024))) {
 
2544
        buf1 = header;
 
2545
        s = headlen;
 
2546
        ret = headlen;
 
2547
        headlen = 0;
 
2548
        header = NULL;
 
2549
      } else {
 
2550
        buf1 = abuf;
 
2551
      }
 
2552
 
 
2553
      if (header && headlen > 0)
 
2554
        {
 
2555
          ret = MIN(headlen,size);
 
2556
          memcpy(buf1,header,ret);
 
2557
          headlen -= ret;
 
2558
          header += ret;
 
2559
          if (headlen <= 0) header = NULL;
 
2560
        }
 
2561
 
 
2562
      if (s > ret)
 
2563
        ret += read(infd,buf1+ret,s-ret);
 
2564
 
 
2565
      if (ret > 0)
 
2566
        {
 
2567
          ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
 
2568
          if (ret2 > 0) total += ret2;
 
2569
          /* if we can't write then dump excess data */
 
2570
          if (ret2 != ret)
 
2571
            transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
 
2572
        }
 
2573
      if (ret <= 0 || ret2 != ret)
 
2574
        return(total);
 
2575
      n -= ret;
 
2576
    }
 
2577
  return(total);
 
2578
}
 
2579
 
 
2580
 
 
2581
/****************************************************************************
 
2582
read 4 bytes of a smb packet and return the smb length of the packet
 
2583
possibly store the result in the buffer
 
2584
****************************************************************************/
 
2585
int read_smb_length(int fd,char *inbuf,int timeout)
 
2586
{
 
2587
  char *buffer;
 
2588
  char buf[4];
 
2589
  int len=0, msg_type;
 
2590
  BOOL ok=False;
 
2591
 
 
2592
  if (inbuf)
 
2593
    buffer = inbuf;
 
2594
  else
 
2595
    buffer = buf;
 
2596
 
 
2597
  while (!ok)
 
2598
    {
 
2599
      if (timeout > 0)
 
2600
        ok = (read_with_timeout(fd,buffer,4,4,timeout,False) == 4);
 
2601
      else      
 
2602
        ok = (read_data(fd,buffer,4) == 4);
 
2603
 
 
2604
      if (!ok)
 
2605
        {
 
2606
          if (timeout>0)
 
2607
            {
 
2608
              DEBUG(10,("select timeout (%d)\n", timeout));
 
2609
              return(-1);
 
2610
            }
 
2611
          else
 
2612
            {
 
2613
              DEBUG(6,("couldn't read from client\n"));
 
2614
              exit(1);
 
2615
            }
 
2616
        }
 
2617
 
 
2618
      len = smb_len(buffer);
 
2619
      msg_type = CVAL(buffer,0);
 
2620
 
 
2621
      if (msg_type == 0x85) 
 
2622
        {
 
2623
          DEBUG(5,( "Got keepalive packet\n"));
 
2624
          ok = False;
 
2625
        }
 
2626
    }
 
2627
 
 
2628
  DEBUG(10,("got smb length of %d\n",len));
 
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 milli seconds
 
2638
****************************************************************************/
 
2639
BOOL receive_smb(int fd,char *buffer,int timeout)
 
2640
{
 
2641
  int len;
 
2642
  BOOL ok;
 
2643
 
 
2644
  bzero(buffer,smb_size + 100);
 
2645
 
 
2646
  len = read_smb_length(fd,buffer,timeout);
 
2647
  if (len == -1)
 
2648
    return(False);
 
2649
 
 
2650
  if (len > BUFFER_SIZE)
 
2651
    {
 
2652
      DEBUG(0,("Invalid packet length! (%d bytes)\n",len));
 
2653
      if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
 
2654
        exit(1);
 
2655
    }
 
2656
 
 
2657
  ok = (read_data(fd,buffer+4,len) == len);
 
2658
 
 
2659
  if (!ok)
 
2660
    {
 
2661
      close_sockets();
 
2662
      exit(1);
 
2663
    }
 
2664
 
 
2665
  return(True);
 
2666
}
 
2667
 
 
2668
 
 
2669
/****************************************************************************
 
2670
  send an smb to a fd 
 
2671
****************************************************************************/
 
2672
BOOL send_smb(int fd,char *buffer)
 
2673
{
 
2674
  int len;
 
2675
  int ret,nwritten=0;
 
2676
  len = smb_len(buffer) + 4;
 
2677
 
 
2678
  while (nwritten < len)
 
2679
    {
 
2680
      ret = write_socket(fd,buffer+nwritten,len - nwritten);
 
2681
      if (ret <= 0)
 
2682
        {
 
2683
          DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
 
2684
          close_sockets();
 
2685
          exit(1);
 
2686
        }
 
2687
      nwritten += ret;
 
2688
    }
 
2689
 
 
2690
 
 
2691
  return True;
 
2692
}
 
2693
 
 
2694
 
 
2695
/****************************************************************************
 
2696
find a pointer to a netbios name
 
2697
****************************************************************************/
 
2698
char *name_ptr(char *buf,int ofs)
 
2699
{
 
2700
  unsigned char c = *(unsigned char *)(buf+ofs);
 
2701
 
 
2702
  if ((c & 0xC0) == 0xC0)
 
2703
    {
 
2704
      uint16 l;
 
2705
      char p[2];
 
2706
      memcpy(p,buf+ofs,2);
 
2707
      p[0] &= ~0xC0;
 
2708
      l = RSVAL(p,0);
 
2709
      DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
 
2710
      return(buf + l);
 
2711
    }
 
2712
  else
 
2713
    return(buf+ofs);
 
2714
}  
 
2715
 
 
2716
/****************************************************************************
 
2717
extract a netbios name from a buf
 
2718
****************************************************************************/
 
2719
int name_extract(char *buf,int ofs,char *name)
 
2720
{
 
2721
  char *p = name_ptr(buf,ofs);
 
2722
  int d = PTR_DIFF(p,buf+ofs);
 
2723
  strcpy(name,"");
 
2724
  if (d < -50 || d > 50) return(0);
 
2725
  return(name_interpret(p,name));
 
2726
}  
 
2727
  
 
2728
 
 
2729
/****************************************************************************
 
2730
return the total storage length of a mangled name
 
2731
****************************************************************************/
 
2732
int name_len(char *s)
 
2733
{
 
2734
  char *s0=s;
 
2735
  unsigned char c = *(unsigned char *)s;
 
2736
  if ((c & 0xC0) == 0xC0)
 
2737
    return(2);
 
2738
  while (*s) s += (*s)+1;
 
2739
  return(PTR_DIFF(s,s0)+1);
 
2740
}
 
2741
 
 
2742
/****************************************************************************
 
2743
send a single packet to a port on another machine
 
2744
****************************************************************************/
 
2745
BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
 
2746
{
 
2747
  BOOL ret;
 
2748
  int out_fd;
 
2749
  struct sockaddr_in sock_out;
 
2750
 
 
2751
  if (passive)
 
2752
    return(True);
 
2753
 
 
2754
  /* create a socket to write to */
 
2755
  out_fd = socket(AF_INET, type, 0);
 
2756
  if (out_fd == -1) 
 
2757
    {
 
2758
      DEBUG(0,("socket failed"));
 
2759
      return False;
 
2760
    }
 
2761
 
 
2762
  /* set the address and port */
 
2763
  bzero((char *)&sock_out,sizeof(sock_out));
 
2764
  putip((char *)&sock_out.sin_addr,(char *)&ip);
 
2765
  sock_out.sin_port = htons( port );
 
2766
  sock_out.sin_family = AF_INET;
 
2767
  
 
2768
  if (DEBUGLEVEL > 0)
 
2769
    DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
 
2770
             len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
 
2771
        
 
2772
  /* send it */
 
2773
  ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
 
2774
 
 
2775
  if (!ret)
 
2776
    DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
 
2777
             inet_ntoa(ip),port,errno));
 
2778
 
 
2779
  close(out_fd);
 
2780
  return(ret);
 
2781
}
 
2782
 
 
2783
/*******************************************************************
 
2784
sleep for a specified number of milliseconds
 
2785
********************************************************************/
 
2786
void msleep(int t)
 
2787
{
 
2788
  int tdiff=0;
 
2789
  struct timeval tval,t1,t2;  
 
2790
  fd_set fds;
 
2791
 
 
2792
  GetTimeOfDay(&t1);
 
2793
  GetTimeOfDay(&t2);
 
2794
  
 
2795
  while (tdiff < t) {
 
2796
    tval.tv_sec = (t-tdiff)/1000;
 
2797
    tval.tv_usec = 1000*((t-tdiff)%1000);
 
2798
 
 
2799
    FD_ZERO(&fds);
 
2800
    errno = 0;
 
2801
    sys_select(&fds,&tval);
 
2802
 
 
2803
    GetTimeOfDay(&t2);
 
2804
    tdiff = TvalDiff(&t1,&t2);
 
2805
  }
 
2806
}
 
2807
 
 
2808
/****************************************************************************
 
2809
check if a string is part of a list
 
2810
****************************************************************************/
 
2811
BOOL in_list(char *s,char *list,BOOL casesensitive)
 
2812
{
 
2813
  pstring tok;
 
2814
  char *p=list;
 
2815
 
 
2816
  if (!list) return(False);
 
2817
 
 
2818
  while (next_token(&p,tok,LIST_SEP))
 
2819
    {
 
2820
      if (casesensitive) {
 
2821
        if (strcmp(tok,s) == 0)
 
2822
          return(True);
 
2823
      } else {
 
2824
        if (StrCaseCmp(tok,s) == 0)
 
2825
          return(True);
 
2826
      }
 
2827
    }
 
2828
  return(False);
 
2829
}
 
2830
 
 
2831
/* this is used to prevent lots of mallocs of size 1 */
 
2832
static char *null_string = NULL;
 
2833
 
 
2834
/****************************************************************************
 
2835
set a string value, allocing the space for the string
 
2836
****************************************************************************/
 
2837
BOOL string_init(char **dest,char *src)
 
2838
{
 
2839
  int l;
 
2840
  if (!src)     
 
2841
    src = "";
 
2842
 
 
2843
  l = strlen(src);
 
2844
 
 
2845
  if (l == 0)
 
2846
    {
 
2847
      if (!null_string)
 
2848
        null_string = (char *)malloc(1);
 
2849
 
 
2850
      *null_string = 0;
 
2851
      *dest = null_string;
 
2852
    }
 
2853
  else
 
2854
    {
 
2855
      *dest = (char *)malloc(l+1);
 
2856
      strcpy(*dest,src);
 
2857
    }
 
2858
  return(True);
 
2859
}
 
2860
 
 
2861
/****************************************************************************
 
2862
free a string value
 
2863
****************************************************************************/
 
2864
void string_free(char **s)
 
2865
{
 
2866
  if (!s || !(*s)) return;
 
2867
  if (*s == null_string)
 
2868
    *s = NULL;
 
2869
  if (*s) free(*s);
 
2870
  *s = NULL;
 
2871
}
 
2872
 
 
2873
/****************************************************************************
 
2874
set a string value, allocing the space for the string, and deallocating any 
 
2875
existing space
 
2876
****************************************************************************/
 
2877
BOOL string_set(char **dest,char *src)
 
2878
{
 
2879
  string_free(dest);
 
2880
 
 
2881
  return(string_init(dest,src));
 
2882
}
 
2883
 
 
2884
/****************************************************************************
 
2885
substitute a string for a pattern in another string. Make sure there is 
 
2886
enough room!
 
2887
 
 
2888
This routine looks for pattern in s and replaces it with 
 
2889
insert. It may do multiple replacements.
 
2890
 
 
2891
return True if a substitution was done.
 
2892
****************************************************************************/
 
2893
BOOL string_sub(char *s,char *pattern,char *insert)
 
2894
{
 
2895
  BOOL ret = False;
 
2896
  char *p;
 
2897
  int ls,lp,li;
 
2898
 
 
2899
  if (!insert || !pattern || !s) return(False);
 
2900
 
 
2901
  ls = strlen(s);
 
2902
  lp = strlen(pattern);
 
2903
  li = strlen(insert);
 
2904
 
 
2905
  if (!*pattern) return(False);
 
2906
 
 
2907
  while (lp <= ls && (p = strstr(s,pattern)))
 
2908
    {
 
2909
      ret = True;
 
2910
      memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
 
2911
      memcpy(p,insert,li);
 
2912
      s = p + li;
 
2913
      ls = strlen(s);
 
2914
    }
 
2915
  return(ret);
 
2916
}
 
2917
 
 
2918
 
 
2919
 
 
2920
/*********************************************************
 
2921
* Recursive routine that is called by mask_match.
 
2922
* Does the actual matching.
 
2923
*********************************************************/
 
2924
BOOL do_match(char *str, char *regexp, int case_sig)
 
2925
{
 
2926
  char *p;
 
2927
 
 
2928
  for( p = regexp; *p && *str; ) {
 
2929
    switch(*p) {
 
2930
    case '?':
 
2931
      str++; p++;
 
2932
      break;
 
2933
 
 
2934
    case '*':
 
2935
      /* Look for a character matching 
 
2936
         the one after the '*' */
 
2937
      p++;
 
2938
      if(!*p)
 
2939
        return True; /* Automatic match */
 
2940
      while(*str) {
 
2941
        while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
 
2942
          str++;
 
2943
        if(do_match(str,p,case_sig))
 
2944
          return True;
 
2945
        if(!*str)
 
2946
          return False;
 
2947
        else
 
2948
          str++;
 
2949
      }
 
2950
      return False;
 
2951
 
 
2952
    default:
 
2953
      if(case_sig) {
 
2954
        if(*str != *p)
 
2955
          return False;
 
2956
      } else {
 
2957
        if(toupper(*str) != toupper(*p))
 
2958
          return False;
 
2959
      }
 
2960
      str++, p++;
 
2961
      break;
 
2962
    }
 
2963
  }
 
2964
  if(!*p && !*str)
 
2965
    return True;
 
2966
 
 
2967
  if (!*p && str[0] == '.' && str[1] == 0)
 
2968
    return(True);
 
2969
  
 
2970
  if (!*str && *p == '?')
 
2971
    {
 
2972
      while (*p == '?') p++;
 
2973
      return(!*p);
 
2974
    }
 
2975
 
 
2976
  if(!*str && (*p == '*' && p[1] == '\0'))
 
2977
    return True;
 
2978
  return False;
 
2979
}
 
2980
 
 
2981
 
 
2982
/*********************************************************
 
2983
* Routine to match a given string with a regexp - uses
 
2984
* simplified regexp that takes * and ? only. Case can be
 
2985
* significant or not.
 
2986
*********************************************************/
 
2987
BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
 
2988
{
 
2989
  char *p;
 
2990
  pstring p1, p2;
 
2991
  fstring ebase,eext,sbase,sext;
 
2992
 
 
2993
  BOOL matched;
 
2994
 
 
2995
  /* Make local copies of str and regexp */
 
2996
  StrnCpy(p1,regexp,sizeof(pstring)-1);
 
2997
  StrnCpy(p2,str,sizeof(pstring)-1);
 
2998
 
 
2999
  if (!strchr(p2,'.')) {
 
3000
    strcat(p2,".");
 
3001
  }
 
3002
 
 
3003
/*
 
3004
  if (!strchr(p1,'.')) {
 
3005
    strcat(p1,".");
 
3006
  }
 
3007
*/
 
3008
 
 
3009
#if 0
 
3010
  if (strchr(p1,'.'))
 
3011
    {
 
3012
      string_sub(p1,"*.*","*");
 
3013
      string_sub(p1,".*","*");
 
3014
    }
 
3015
#endif
 
3016
 
 
3017
  /* Remove any *? and ** as they are meaningless */
 
3018
  for(p = p1; *p; p++)
 
3019
    while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
 
3020
      (void)strcpy( &p[1], &p[2]);
 
3021
 
 
3022
  if (strequal(p1,"*")) return(True);
 
3023
 
 
3024
  DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
 
3025
 
 
3026
  if (trans2) {
 
3027
    strcpy(ebase,p1);
 
3028
    strcpy(sbase,p2);
 
3029
  } else {
 
3030
    if ((p=strrchr(p1,'.'))) {
 
3031
      *p = 0;
 
3032
      strcpy(ebase,p1);
 
3033
      strcpy(eext,p+1);
 
3034
    } else {
 
3035
      strcpy(ebase,p1);
 
3036
      eext[0] = 0;
 
3037
    }
 
3038
 
 
3039
  if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
 
3040
    *p = 0;
 
3041
    strcpy(sbase,p2);
 
3042
    strcpy(sext,p+1);
 
3043
  } else {
 
3044
    strcpy(sbase,p2);
 
3045
    strcpy(sext,"");
 
3046
  }
 
3047
  }
 
3048
 
 
3049
  matched = do_match(sbase,ebase,case_sig) && 
 
3050
    (trans2 || do_match(sext,eext,case_sig));
 
3051
 
 
3052
  DEBUG(5,("mask_match returning %d\n", matched));
 
3053
 
 
3054
  return matched;
 
3055
}
 
3056
 
 
3057
#ifndef SCANNER
 
3058
/****************************************************************************
 
3059
become a daemon, discarding the controlling terminal
 
3060
****************************************************************************/
 
3061
void become_daemon(void)
 
3062
{
 
3063
#ifndef NO_FORK_DEBUG
 
3064
  if (fork())
 
3065
    exit(0);
 
3066
 
 
3067
  /* detach from the terminal */
 
3068
#ifdef USE_SETSID
 
3069
  setsid();
 
3070
#else
 
3071
#ifdef TIOCNOTTY
 
3072
  {
 
3073
    int i = open("/dev/tty", O_RDWR);
 
3074
    if (i >= 0) 
 
3075
      {
 
3076
        ioctl(i, (int) TIOCNOTTY, (char *)0);      
 
3077
        close(i);
 
3078
      }
 
3079
  }
 
3080
#endif
 
3081
#endif
 
3082
#endif
 
3083
}
 
3084
#endif /* SCANNER */
 
3085
 
 
3086
/****************************************************************************
 
3087
calculate the default netmask for an address
 
3088
****************************************************************************/
 
3089
static void default_netmask(struct in_addr *inm, struct in_addr *iad)
 
3090
{
 
3091
  unsigned long ad = ntohl(iad->s_addr);
 
3092
  unsigned long nm;
 
3093
  /*
 
3094
  ** Guess a netmask based on the class of the IP address given.
 
3095
  */
 
3096
  if ( (ad & 0x80000000) == 0 ) {
 
3097
    /* class A address */
 
3098
    nm = 0xFF000000;
 
3099
  } else if ( (ad & 0xC0000000) == 0x80000000 ) {
 
3100
    /* class B address */
 
3101
    nm = 0xFFFF0000;
 
3102
  } else if ( (ad & 0xE0000000) == 0xC0000000 ) {
 
3103
    /* class C address */
 
3104
    nm = 0xFFFFFF00;
 
3105
  }  else {
 
3106
    /* class D or E; netmask doesn't make much sense - guess 4 bits */
 
3107
    nm =  0xFFFFFFF0;
 
3108
  }
 
3109
  inm->s_addr = htonl(nm);
 
3110
}
 
3111
 
 
3112
/****************************************************************************
 
3113
  get the broadcast address for our address 
 
3114
(troyer@saifr00.ateng.az.honeywell.com)
 
3115
****************************************************************************/
 
3116
void get_broadcast(struct in_addr *if_ipaddr,
 
3117
                    struct in_addr *if_bcast,
 
3118
                    struct in_addr *if_nmask)
 
3119
{  
 
3120
  BOOL found = False;
 
3121
#ifndef NO_GET_BROADCAST
 
3122
  int sock = -1;               /* AF_INET raw socket desc */
 
3123
  char buff[1024];
 
3124
  struct ifreq *ifr=NULL;
 
3125
  int i;
 
3126
 
 
3127
#if defined(EVEREST)
 
3128
  int n_interfaces;
 
3129
  struct ifconf ifc;
 
3130
  struct ifreq  *ifreqs;
 
3131
#elif defined(USE_IFREQ)
 
3132
  struct ifreq ifreq;
 
3133
  struct strioctl strioctl;
 
3134
  struct ifconf *ifc;
 
3135
#else
 
3136
  struct ifconf ifc;
 
3137
#endif
 
3138
#endif
 
3139
 
 
3140
  /* get a default netmask and broadcast */
 
3141
  default_netmask(if_nmask, if_ipaddr);
 
3142
 
 
3143
#ifndef NO_GET_BROADCAST  
 
3144
  /* Create a socket to the INET kernel. */
 
3145
#if USE_SOCKRAW
 
3146
  if ((sock = socket(AF_INET, SOCK_RAW, PF_INET )) < 0)
 
3147
#else
 
3148
    if ((sock = socket(AF_INET, SOCK_DGRAM, 0 )) < 0)
 
3149
#endif
 
3150
      {
 
3151
        DEBUG(0,( "Unable to open socket to get broadcast address\n"));
 
3152
        return;
 
3153
      }
 
3154
  
 
3155
  /* Get a list of the configured interfaces */
 
3156
#ifdef EVEREST
 
3157
  /* This is part of SCO Openserver 5: The ioctls are no longer part
 
3158
     if the lower level STREAMS interface glue. They are now real
 
3159
     ioctl calls */
 
3160
 
 
3161
  if (ioctl(sock, SIOCGIFANUM, &n_interfaces) < 0) {
 
3162
    DEBUG(0,( "SIOCGIFANUM: %s\n", strerror(errno)));
 
3163
  } else {
 
3164
    DEBUG(0,( "number of interfaces returned is: %d\n", n_interfaces));
 
3165
 
 
3166
    ifc.ifc_len = sizeof(struct ifreq) * n_interfaces;
 
3167
    ifc.ifc_buf = (caddr_t) alloca(ifc.ifc_len);
 
3168
 
 
3169
    if (ioctl(sock, SIOCGIFCONF, &ifc) < 0)
 
3170
      DEBUG(0, ( "SIOCGIFCONF: %s\n", strerror(errno)));
 
3171
    else {
 
3172
      ifr = ifc.ifc_req;
 
3173
 
 
3174
      for (i = 0; i < n_interfaces; ++i) {
 
3175
        if (if_ipaddr->s_addr ==
 
3176
            ((struct sockaddr_in *) &ifr[i].ifr_addr)->sin_addr.s_addr) {
 
3177
          found = True;
 
3178
          break;
 
3179
        }
 
3180
      }
 
3181
    }
 
3182
  }
 
3183
#elif defined(USE_IFREQ)
 
3184
  ifc = (struct ifconf *)buff;
 
3185
  ifc->ifc_len = BUFSIZ - sizeof(struct ifconf);
 
3186
  strioctl.ic_cmd = SIOCGIFCONF;
 
3187
  strioctl.ic_dp  = (char *)ifc;
 
3188
  strioctl.ic_len = sizeof(buff);
 
3189
  if (ioctl(sock, I_STR, &strioctl) < 0) {
 
3190
    DEBUG(0,( "I_STR/SIOCGIFCONF: %s\n", strerror(errno)));
 
3191
  } else {
 
3192
    ifr = (struct ifreq *)ifc->ifc_req;  
 
3193
 
 
3194
    /* Loop through interfaces, looking for given IP address */
 
3195
    for (i = ifc->ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
 
3196
      if (if_ipaddr->s_addr ==
 
3197
          (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
 
3198
        found = True;
 
3199
        break;
 
3200
      }
 
3201
    }
 
3202
  }
 
3203
#elif defined(__FreeBSD__) || defined(NETBSD) || defined(OPENBSD)
 
3204
  ifc.ifc_len = sizeof(buff);
 
3205
  ifc.ifc_buf = buff;
 
3206
  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
 
3207
    DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
 
3208
  } else {
 
3209
    ifr = ifc.ifc_req;
 
3210
    /* Loop through interfaces, looking for given IP address */
 
3211
    i = ifc.ifc_len;
 
3212
    while (i > 0) {
 
3213
      if (if_ipaddr->s_addr ==
 
3214
          (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
 
3215
        found = True;
 
3216
        break;
 
3217
      }
 
3218
      i -= ifr->ifr_addr.sa_len + IFNAMSIZ;
 
3219
      ifr = (struct ifreq*) ((char*) ifr + ifr->ifr_addr.sa_len + IFNAMSIZ);
 
3220
    }
 
3221
  }
 
3222
#else
 
3223
  ifc.ifc_len = sizeof(buff);
 
3224
  ifc.ifc_buf = buff;
 
3225
  if (ioctl(sock, SIOCGIFCONF, &ifc) < 0) {
 
3226
    DEBUG(0,("SIOCGIFCONF: %s\n", strerror(errno)));
 
3227
  } else {
 
3228
    ifr = ifc.ifc_req;
 
3229
  
 
3230
    /* Loop through interfaces, looking for given IP address */
 
3231
    for (i = ifc.ifc_len / sizeof(struct ifreq); --i >= 0; ifr++) {
 
3232
#ifdef BSDI
 
3233
      if (ioctl(sock, SIOCGIFADDR, ifr) < 0) break;
 
3234
#endif
 
3235
      if (if_ipaddr->s_addr ==
 
3236
          (*(struct sockaddr_in *) &ifr->ifr_addr).sin_addr.s_addr) {
 
3237
        found = True;
 
3238
        break;
 
3239
      }
 
3240
    }
 
3241
  }
 
3242
#endif
 
3243
  
 
3244
  if (!found) {
 
3245
    DEBUG(0,("No interface found for address %s\n", inet_ntoa(*if_ipaddr)));
 
3246
  } else {
 
3247
    /* Get the netmask address from the kernel */
 
3248
#ifdef USE_IFREQ
 
3249
    ifreq = *ifr;
 
3250
  
 
3251
    strioctl.ic_cmd = SIOCGIFNETMASK;
 
3252
    strioctl.ic_dp  = (char *)&ifreq;
 
3253
    strioctl.ic_len = sizeof(struct ifreq);
 
3254
    if (ioctl(sock, I_STR, &strioctl) < 0)
 
3255
      DEBUG(0,("Failed I_STR/SIOCGIFNETMASK: %s\n", strerror(errno)));
 
3256
    else
 
3257
      *if_nmask = ((struct sockaddr_in *)&ifreq.ifr_addr)->sin_addr;
 
3258
#else
 
3259
    if (ioctl(sock, SIOCGIFNETMASK, ifr) < 0)
 
3260
      DEBUG(0,("SIOCGIFNETMASK failed\n"));
 
3261
    else
 
3262
      *if_nmask = ((struct sockaddr_in *)&ifr->ifr_addr)->sin_addr;
 
3263
#endif
 
3264
 
 
3265
    DEBUG(2,("Netmask for %s = %s\n", ifr->ifr_name,
 
3266
             inet_ntoa(*if_nmask)));
 
3267
  }
 
3268
 
 
3269
  /* Close up shop */
 
3270
  (void) close(sock);
 
3271
  
 
3272
#endif
 
3273
 
 
3274
  /* sanity check on the netmask */
 
3275
  {
 
3276
    unsigned long nm = ntohl(if_nmask->s_addr);
 
3277
    if ((nm >> 24) != 0xFF) {
 
3278
      DEBUG(0,("Impossible netmask %s - using defaults\n",inet_ntoa(*if_nmask)));
 
3279
      default_netmask(if_nmask, if_ipaddr);      
 
3280
    }
 
3281
  }
 
3282
 
 
3283
  /* derive the broadcast assuming a 1's broadcast, as this is what
 
3284
     all MS operating systems do, we have to comply even if the unix
 
3285
     box is setup differently */
 
3286
  {
 
3287
    unsigned long ad = ntohl(if_ipaddr->s_addr);
 
3288
    unsigned long nm = ntohl(if_nmask->s_addr);
 
3289
    unsigned long bc = (ad & nm) | (0xffffffff & ~nm);
 
3290
    if_bcast->s_addr = htonl(bc);
 
3291
  }
 
3292
  
 
3293
  DEBUG(2,("Derived broadcast address %s\n", inet_ntoa(*if_bcast)));
 
3294
}  /* get_broadcast */
 
3295
 
 
3296
 
 
3297
/****************************************************************************
 
3298
put up a yes/no prompt
 
3299
****************************************************************************/
 
3300
BOOL yesno(char *p)
 
3301
{
 
3302
  pstring ans;
 
3303
  printf("%s",p);
 
3304
 
 
3305
  if (!fgets(ans,sizeof(ans)-1,stdin))
 
3306
    return(False);
 
3307
 
 
3308
  if (*ans == 'y' || *ans == 'Y')
 
3309
    return(True);
 
3310
 
 
3311
  return(False);
 
3312
}
 
3313
 
 
3314
/****************************************************************************
 
3315
read a line from a file with possible \ continuation chars. 
 
3316
Blanks at the start or end of a line are stripped.
 
3317
The string will be allocated if s2 is NULL
 
3318
****************************************************************************/
 
3319
char *fgets_slash(char *s2,int maxlen,FILE *f)
 
3320
{
 
3321
  char *s=s2;
 
3322
  int len = 0;
 
3323
  int c;
 
3324
  BOOL start_of_line = True;
 
3325
 
 
3326
  if (feof(f))
 
3327
    return(NULL);
 
3328
 
 
3329
  if (!s2)
 
3330
    {
 
3331
      maxlen = MIN(maxlen,8);
 
3332
      s = (char *)Realloc(s,maxlen);
 
3333
    }
 
3334
 
 
3335
  if (!s || maxlen < 2) return(NULL);
 
3336
 
 
3337
  *s = 0;
 
3338
 
 
3339
  while (len < maxlen-1)
 
3340
    {
 
3341
      c = getc(f);
 
3342
      switch (c)
 
3343
        {
 
3344
        case '\r':
 
3345
          break;
 
3346
        case '\n':
 
3347
          while (len > 0 && s[len-1] == ' ')
 
3348
            {
 
3349
              s[--len] = 0;
 
3350
            }
 
3351
          if (len > 0 && s[len-1] == '\\')
 
3352
            {
 
3353
              s[--len] = 0;
 
3354
              start_of_line = True;
 
3355
              break;
 
3356
            }
 
3357
          return(s);
 
3358
        case EOF:
 
3359
          if (len <= 0 && !s2) 
 
3360
            free(s);
 
3361
          return(len>0?s:NULL);
 
3362
        case ' ':
 
3363
          if (start_of_line)
 
3364
            break;
 
3365
        default:
 
3366
          start_of_line = False;
 
3367
          s[len++] = c;
 
3368
          s[len] = 0;
 
3369
        }
 
3370
      if (!s2 && len > maxlen-3)
 
3371
        {
 
3372
          maxlen *= 2;
 
3373
          s = (char *)Realloc(s,maxlen);
 
3374
          if (!s) return(NULL);
 
3375
        }
 
3376
    }
 
3377
  return(s);
 
3378
}
 
3379
 
 
3380
 
 
3381
 
 
3382
/****************************************************************************
 
3383
set the length of a file from a filedescriptor.
 
3384
Returns 0 on success, -1 on failure.
 
3385
****************************************************************************/
 
3386
int set_filelen(int fd, long len)
 
3387
{
 
3388
/* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
 
3389
   extend a file with ftruncate. Provide alternate implementation
 
3390
   for this */
 
3391
 
 
3392
#if FTRUNCATE_CAN_EXTEND
 
3393
  return ftruncate(fd, len);
 
3394
#else
 
3395
  struct stat st;
 
3396
  char c = 0;
 
3397
  long currpos = lseek(fd, 0L, SEEK_CUR);
 
3398
 
 
3399
  if(currpos < 0)
 
3400
    return -1;
 
3401
  /* Do an fstat to see if the file is longer than
 
3402
     the requested size (call ftruncate),
 
3403
     or shorter, in which case seek to len - 1 and write 1
 
3404
     byte of zero */
 
3405
  if(fstat(fd, &st)<0)
 
3406
    return -1;
 
3407
 
 
3408
#ifdef S_ISFIFO
 
3409
  if (S_ISFIFO(st.st_mode)) return 0;
 
3410
#endif
 
3411
 
 
3412
  if(st.st_size == len)
 
3413
    return 0;
 
3414
  if(st.st_size > len)
 
3415
    return ftruncate(fd, len);
 
3416
 
 
3417
  if(lseek(fd, len-1, SEEK_SET) != len -1)
 
3418
    return -1;
 
3419
  if(write(fd, &c, 1)!=1)
 
3420
    return -1;
 
3421
  /* Seek to where we were */
 
3422
  lseek(fd, currpos, SEEK_SET);
 
3423
  return 0;
 
3424
#endif
 
3425
}
 
3426
 
 
3427
 
 
3428
/****************************************************************************
 
3429
return the byte checksum of some data
 
3430
****************************************************************************/
 
3431
int byte_checksum(char *buf,int len)
 
3432
{
 
3433
  unsigned char *p = (unsigned char *)buf;
 
3434
  int ret = 0;
 
3435
  while (len--)
 
3436
    ret += *p++;
 
3437
  return(ret);
 
3438
}
 
3439
 
 
3440
 
 
3441
 
 
3442
#ifdef HPUX
 
3443
/****************************************************************************
 
3444
this is a version of setbuffer() for those machines that only have setvbuf
 
3445
****************************************************************************/
 
3446
void setbuffer(FILE *f,char *buf,int bufsize)
 
3447
{
 
3448
  setvbuf(f,buf,_IOFBF,bufsize);
 
3449
}
 
3450
#endif
 
3451
 
 
3452
 
 
3453
/****************************************************************************
 
3454
parse out a directory name from a path name. Assumes dos style filenames.
 
3455
****************************************************************************/
 
3456
char *dirname_dos(char *path,char *buf)
 
3457
{
 
3458
  char *p = strrchr(path,'\\');
 
3459
 
 
3460
  if (!p)
 
3461
    strcpy(buf,path);
 
3462
  else
 
3463
    {
 
3464
      *p = 0;
 
3465
      strcpy(buf,path);
 
3466
      *p = '\\';
 
3467
    }
 
3468
 
 
3469
  return(buf);
 
3470
}
 
3471
 
 
3472
 
 
3473
/****************************************************************************
 
3474
parse out a filename from a path name. Assumes dos style filenames.
 
3475
****************************************************************************/
 
3476
static char *filename_dos(char *path,char *buf)
 
3477
{
 
3478
  char *p = strrchr(path,'\\');
 
3479
 
 
3480
  if (!p)
 
3481
    strcpy(buf,path);
 
3482
  else
 
3483
    strcpy(buf,p+1);
 
3484
 
 
3485
  return(buf);
 
3486
}
 
3487
 
 
3488
 
 
3489
 
 
3490
/****************************************************************************
 
3491
expand a pointer to be a particular size
 
3492
****************************************************************************/
 
3493
void *Realloc(void *p,int size)
 
3494
{
 
3495
  void *ret=NULL;
 
3496
  if (!p)
 
3497
    ret = (void *)malloc(size);
 
3498
  else
 
3499
    ret = (void *)realloc(p,size);
 
3500
 
 
3501
  if (!ret)
 
3502
    DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
 
3503
 
 
3504
  return(ret);
 
3505
}
 
3506
 
 
3507
/****************************************************************************
 
3508
set the time on a file
 
3509
****************************************************************************/
 
3510
BOOL set_filetime(char *fname,time_t mtime)
 
3511
{  
 
3512
  struct utimbuf times;
 
3513
 
 
3514
  if (null_mtime(mtime)) return(True);
 
3515
 
 
3516
  times.modtime = times.actime = mtime;
 
3517
 
 
3518
  if (sys_utime(fname,&times)) {
 
3519
    DEBUG(4,("set_filetime(%s) failed: %s\n",fname,strerror(errno)));
 
3520
  }
 
3521
    
 
3522
  return(True);
 
3523
}
 
3524
 
 
3525
 
 
3526
#ifdef NOSTRDUP
 
3527
/****************************************************************************
 
3528
duplicate a string
 
3529
****************************************************************************/
 
3530
char *strdup(char *s)
 
3531
{
 
3532
  char *ret = NULL;
 
3533
  if (!s) return(NULL);
 
3534
  ret = (char *)malloc(strlen(s)+1);
 
3535
  if (!ret) return(NULL);
 
3536
  strcpy(ret,s);
 
3537
  return(ret);
 
3538
}
 
3539
#endif
 
3540
 
 
3541
#ifndef SCANNER
 
3542
 
 
3543
/****************************************************************************
 
3544
  Signal handler for SIGPIPE (write on a disconnected socket) 
 
3545
****************************************************************************/
 
3546
void Abort(void )
 
3547
{
 
3548
  DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
 
3549
  exit(2);
 
3550
}
 
3551
#endif /* SCANNER */
 
3552
 
 
3553
#ifdef REPLACE_STRLEN
 
3554
/****************************************************************************
 
3555
a replacement strlen() that returns int for solaris
 
3556
****************************************************************************/
 
3557
int Strlen(char *s)
 
3558
{
 
3559
  int ret=0;
 
3560
  if (!s) return(0);
 
3561
  while (*s++) ret++;
 
3562
  return(ret);
 
3563
}
 
3564
#endif
 
3565
 
 
3566
 
 
3567
/****************************************************************************
 
3568
return a time at the start of the current month
 
3569
****************************************************************************/
 
3570
time_t start_of_month(void)
 
3571
{
 
3572
  time_t t = time(NULL);
 
3573
  struct tm *t2;
 
3574
  
 
3575
  t2 = gmtime(&t);
 
3576
  
 
3577
  t2->tm_mday = 1;
 
3578
  t2->tm_hour = 0;
 
3579
  t2->tm_min = 0;
 
3580
  t2->tm_sec = 0;
 
3581
  
 
3582
  return(mktime(t2));
 
3583
}
 
3584
 
 
3585
 
 
3586
/*******************************************************************
 
3587
  check for a sane unix date
 
3588
********************************************************************/
 
3589
BOOL sane_unix_date(time_t unixdate)
 
3590
{
 
3591
  struct tm t,today;
 
3592
  time_t t_today = time(NULL);
 
3593
  
 
3594
  t = *(LocalTime(&unixdate,LOCAL_TO_GMT));
 
3595
  today = *(LocalTime(&t_today,LOCAL_TO_GMT));
 
3596
  
 
3597
  if (t.tm_year < 80)
 
3598
    return(False);
 
3599
  
 
3600
  if (t.tm_year >  today.tm_year)
 
3601
    return(False);
 
3602
  
 
3603
  if (t.tm_year == today.tm_year &&
 
3604
      t.tm_mon > today.tm_mon)
 
3605
    return(False);
 
3606
  
 
3607
  
 
3608
  if (t.tm_year == today.tm_year &&
 
3609
      t.tm_mon == today.tm_mon &&
 
3610
      t.tm_mday > (today.tm_mday+1))
 
3611
    return(False);
 
3612
  
 
3613
  return(True);
 
3614
}
 
3615
 
 
3616
 
 
3617
 
 
3618
#ifdef NO_FTRUNCATE
 
3619
 /*******************************************************************
 
3620
ftruncate for operating systems that don't have it
 
3621
********************************************************************/
 
3622
int ftruncate(int f,long l)
 
3623
{
 
3624
      struct  flock   fl;
 
3625
 
 
3626
      fl.l_whence = 0;
 
3627
      fl.l_len = 0;
 
3628
      fl.l_start = l;
 
3629
      fl.l_type = F_WRLCK;
 
3630
      return fcntl(f, F_FREESP, &fl);
 
3631
}
 
3632
#endif
 
3633
 
 
3634
 
 
3635
 
 
3636
/****************************************************************************
 
3637
get my own name and IP
 
3638
****************************************************************************/
 
3639
BOOL get_myname(char *myname,struct in_addr *ip)
 
3640
{
 
3641
  struct hostent *hp;
 
3642
  pstring hostname;
 
3643
 
 
3644
  *hostname = 0;
 
3645
 
 
3646
  /* get my host name */
 
3647
  if (gethostname(hostname, MAXHOSTNAMELEN) == -1) 
 
3648
    {
 
3649
      DEBUG(0,("gethostname failed\n"));
 
3650
      return False;
 
3651
    } 
 
3652
 
 
3653
  /* get host info */
 
3654
  if ((hp = Get_Hostbyname(hostname)) == 0) 
 
3655
    {
 
3656
      DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
 
3657
      return False;
 
3658
    }
 
3659
 
 
3660
  if (myname)
 
3661
    {
 
3662
      /* split off any parts after an initial . */
 
3663
      char *p = strchr(hostname,'.');
 
3664
      if (p) *p = 0;
 
3665
 
 
3666
      strcpy(myname,hostname);
 
3667
    }
 
3668
 
 
3669
  if (ip)
 
3670
    putip((char *)ip,(char *)hp->h_addr);
 
3671
 
 
3672
  return(True);
 
3673
}
 
3674
 
 
3675
 
 
3676
/****************************************************************************
 
3677
true if two IP addresses are equal
 
3678
****************************************************************************/
 
3679
BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
 
3680
{
 
3681
  unsigned long a1,a2;
 
3682
  a1 = ntohl(ip1.s_addr);
 
3683
  a2 = ntohl(ip2.s_addr);
 
3684
  return(a1 == a2);
 
3685
}
 
3686
 
 
3687
 
 
3688
/****************************************************************************
 
3689
open a socket of the specified type, port and address for incoming data
 
3690
****************************************************************************/
 
3691
int open_socket_in(int type, int port, int dlevel)
 
3692
{
 
3693
  struct hostent *hp;
 
3694
  struct sockaddr_in sock;
 
3695
  pstring host_name;
 
3696
  int res;
 
3697
 
 
3698
#ifdef SCANNER
 
3699
/* skip all this lookup nonsense and just plug the stuff in like our
 
3700
   IQ was normal, eh? */
 
3701
  bzero ((char *)&sock, sizeof (sock));
 
3702
  sock.sin_port = htons (port);
 
3703
  sock.sin_family = AF_INET;
 
3704
  sock.sin_addr.s_addr = INADDR_ANY;
 
3705
  res = socket (AF_INET, type, 0);
 
3706
#else
 
3707
  /* get my host name */
 
3708
#ifdef MAXHOSTNAMELEN
 
3709
  if (gethostname(host_name, MAXHOSTNAMELEN) == -1) 
 
3710
#else
 
3711
  if (gethostname(host_name, sizeof(host_name)) == -1) 
 
3712
#endif
 
3713
    { DEBUG(0,("gethostname failed\n")); return -1; } 
 
3714
 
 
3715
  /* get host info */
 
3716
  if ((hp = Get_Hostbyname(host_name)) == 0) 
 
3717
    {
 
3718
      DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
 
3719
      return -1;
 
3720
    }
 
3721
  
 
3722
  bzero((char *)&sock,sizeof(sock));
 
3723
  memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
 
3724
#if defined(__FreeBSD__) || defined(NETBSD) || defined(OPENBSD)
 
3725
  sock.sin_len = sizeof(sock);
 
3726
#endif
 
3727
  sock.sin_port = htons( port );
 
3728
  sock.sin_family = hp->h_addrtype;
 
3729
  sock.sin_addr.s_addr = INADDR_ANY;
 
3730
  res = socket(hp->h_addrtype, type, 0);
 
3731
#endif /* SCANNER */
 
3732
  if (res == -1) 
 
3733
    { DEBUG(0,("socket failed\n")); return -1; }
 
3734
 
 
3735
  {
 
3736
    int one=1;
 
3737
    setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
 
3738
  }
 
3739
 
 
3740
  /* now we've got a socket - we need to bind it */
 
3741
  if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0) 
 
3742
    { 
 
3743
      if (port) {
 
3744
        if (port == 139 || port == 137)
 
3745
          DEBUG(dlevel,("bind failed on port %d (%s)\n",
 
3746
                        port,strerror(errno))); 
 
3747
        close(res); 
 
3748
 
 
3749
        if (dlevel > 0 && port < 1000)
 
3750
          port = 7999;
 
3751
 
 
3752
        if (port >= 1000 && port < 9000)
 
3753
          return(open_socket_in(type,port+1,dlevel));
 
3754
      }
 
3755
 
 
3756
      return(-1); 
 
3757
    }
 
3758
  DEBUG(3,("bind succeeded on port %d\n",port));
 
3759
 
 
3760
  return res;
 
3761
}
 
3762
 
 
3763
 
 
3764
/****************************************************************************
 
3765
  create an outgoing socket
 
3766
  **************************************************************************/
 
3767
int open_socket_out(int type, struct in_addr *addr, int port )
 
3768
{
 
3769
  struct sockaddr_in sock_out;
 
3770
  int res;
 
3771
 
 
3772
  /* create a socket to write to */
 
3773
  res = socket(PF_INET, type, 0);
 
3774
  if (res == -1) 
 
3775
    { DEBUG(0,("socket error\n")); return -1; }
 
3776
 
 
3777
  if (type != SOCK_STREAM) return(res);
 
3778
  
 
3779
  bzero((char *)&sock_out,sizeof(sock_out));
 
3780
  putip((char *)&sock_out.sin_addr,(char *)addr);
 
3781
  
 
3782
  sock_out.sin_port = htons( port );
 
3783
  sock_out.sin_family = PF_INET;
 
3784
 
 
3785
  DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
 
3786
  
 
3787
  /* and connect it to the destination */
 
3788
  if (connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out))<0) {
 
3789
    DEBUG(0,("connect error: %s\n",strerror(errno))); 
 
3790
    close(res); 
 
3791
    return(-1);
 
3792
  }
 
3793
 
 
3794
  return res;
 
3795
}
 
3796
 
 
3797
 
 
3798
/****************************************************************************
 
3799
interpret a protocol description string, with a default
 
3800
****************************************************************************/
 
3801
int interpret_protocol(char *str,int def)
 
3802
{
 
3803
  if (strequal(str,"NT1"))
 
3804
    return(PROTOCOL_NT1);
 
3805
  if (strequal(str,"LANMAN2"))
 
3806
    return(PROTOCOL_LANMAN2);
 
3807
  if (strequal(str,"LANMAN1"))
 
3808
    return(PROTOCOL_LANMAN1);
 
3809
  if (strequal(str,"CORE"))
 
3810
    return(PROTOCOL_CORE);
 
3811
  if (strequal(str,"COREPLUS"))
 
3812
    return(PROTOCOL_COREPLUS);
 
3813
  if (strequal(str,"CORE+"))
 
3814
    return(PROTOCOL_COREPLUS);
 
3815
  
 
3816
  DEBUG(0,("Unrecognised protocol level %s\n",str));
 
3817
  
 
3818
  return(def);
 
3819
}
 
3820
 
 
3821
/****************************************************************************
 
3822
interpret a security level
 
3823
****************************************************************************/
 
3824
int interpret_security(char *str,int def)
 
3825
{
 
3826
  if (strequal(str,"SERVER"))
 
3827
    return(SEC_SERVER);
 
3828
  if (strequal(str,"USER"))
 
3829
    return(SEC_USER);
 
3830
  if (strequal(str,"SHARE"))
 
3831
    return(SEC_SHARE);
 
3832
  
 
3833
  DEBUG(0,("Unrecognised security level %s\n",str));
 
3834
  
 
3835
  return(def);
 
3836
}
 
3837
 
 
3838
 
 
3839
/****************************************************************************
 
3840
interpret an internet address or name into an IP address in 4 byte form
 
3841
****************************************************************************/
 
3842
unsigned long interpret_addr(char *str)
 
3843
{
 
3844
  struct hostent *hp;
 
3845
  unsigned long res;
 
3846
 
 
3847
  if (strcmp(str,"0.0.0.0") == 0) return(0);
 
3848
  if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
 
3849
 
 
3850
/* SCANNER: XXX: wrong assumption! what about 3com.com... */
 
3851
/* should return struct in_addr, too, even if it *is* ulong */
 
3852
 
 
3853
  /* if it's in the form of an IP address then get the lib to interpret it */
 
3854
  if (isdigit(str[0])) {
 
3855
    res = inet_addr(str);
 
3856
  } else {
 
3857
    /* otherwise assume it's a network name of some sort and use Get_Hostbyname */
 
3858
    if ((hp = Get_Hostbyname(str)) == 0) {
 
3859
      DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
 
3860
      return 0;
 
3861
    }
 
3862
    putip((char *)&res,(char *)hp->h_addr);
 
3863
  }
 
3864
 
 
3865
  if (res == (unsigned long)-1) return(0);
 
3866
 
 
3867
  return(res);
 
3868
}
 
3869
 
 
3870
#ifdef SCANNER
 
3871
 
 
3872
#define GH_SLEAZE 1
 
3873
#ifdef GH_SLEAZE
 
3874
#include <setjmp.h>
 
3875
jmp_buf gh_buf;
 
3876
static void tmx()
 
3877
{
 
3878
  longjmp (gh_buf, 1);
 
3879
}
 
3880
#endif /* GH_SLEAZE */
 
3881
 
 
3882
char * Get_Hostbyaddr (struct in_addr ip)
 
3883
{
 
3884
  static char outbuf [MAXHOSTNAMELEN + 4];      /* reused on every call */
 
3885
  struct hostent * hp;
 
3886
 
 
3887
  if (zero_ip (ip))
 
3888
    return (NULL);
 
3889
#ifdef GH_SLEAZE
 
3890
  signal (SIGALRM, tmx);
 
3891
  alarm (5);
 
3892
  if (setjmp (gh_buf) > 0)
 
3893
    return (NULL);
 
3894
#endif
 
3895
  hp = gethostbyaddr ((char *) &ip, sizeof (struct in_addr), AF_INET);
 
3896
#ifdef GH_SLEAZE
 
3897
  signal (SIGALRM, SIG_DFL);
 
3898
  alarm (0);
 
3899
#endif
 
3900
  if (hp && (hp->h_name)) {
 
3901
    strncpy (outbuf, hp->h_name, MAXHOSTNAMELEN);
 
3902
    outbuf[MAXHOSTNAMELEN] = '\0';
 
3903
    strupper (outbuf);
 
3904
    return (outbuf);
 
3905
  }
 
3906
  return (NULL);
 
3907
} /* Get_Hostbyaddr */
 
3908
 
 
3909
#endif /* SCANNER */
 
3910
 
 
3911
/*******************************************************************
 
3912
  a convenient addition to interpret_addr()
 
3913
  ******************************************************************/
 
3914
struct in_addr *interpret_addr2(char *str)
 
3915
{
 
3916
  static struct in_addr ret;
 
3917
  unsigned long a = interpret_addr(str);
 
3918
  putip((char *)&ret,(char *)&a);
 
3919
  return(&ret);
 
3920
}
 
3921
 
 
3922
/*******************************************************************
 
3923
  check if an IP is the 0.0.0.0
 
3924
  ******************************************************************/
 
3925
BOOL zero_ip(struct in_addr ip)
 
3926
{
 
3927
  unsigned long a;
 
3928
  putip((char *)&a,(char *)&ip);
 
3929
  return(a == 0);
 
3930
}
 
3931
 
 
3932
#define TIME_FIXUP_CONSTANT (369.0*365.25*24*60*60-(3.0*24*60*60+6.0*60*60))
 
3933
 
 
3934
/****************************************************************************
 
3935
interpret an 8 byte "filetime" structure to a time_t
 
3936
It's originally in "100ns units since jan 1st 1601"
 
3937
 
 
3938
It appears to be kludge-GMT (at least for file listings). This means
 
3939
its the GMT you get by taking a localtime and adding the
 
3940
serverzone. This is NOT the same as GMT in some cases. This routine
 
3941
converts this to real GMT.
 
3942
****************************************************************************/
 
3943
time_t interpret_long_date(char *p)
 
3944
{
 
3945
  double d;
 
3946
  time_t ret;
 
3947
  uint32 tlow,thigh;
 
3948
  tlow = IVAL(p,0);
 
3949
  thigh = IVAL(p,4);
 
3950
 
 
3951
  if (thigh == 0) return(0);
 
3952
 
 
3953
  d = ((double)thigh)*4.0*(double)(1<<30);
 
3954
  d += (tlow&0xFFF00000);
 
3955
  d *= 1.0e-7;
 
3956
 
 
3957
  /* now adjust by 369 years to make the secs since 1970 */
 
3958
  d -= TIME_FIXUP_CONSTANT;
 
3959
 
 
3960
  if (d>=MAXINT)
 
3961
    return(0);
 
3962
 
 
3963
  ret = (time_t)(d+0.5);
 
3964
 
 
3965
  /* this takes us from kludge-GMT to real GMT */
 
3966
  ret += TimeDiff(ret) - serverzone;
 
3967
 
 
3968
  return(ret);
 
3969
}
 
3970
 
 
3971
 
 
3972
/****************************************************************************
 
3973
put a 8 byte filetime from a time_t
 
3974
This takes real GMT as input and converts to kludge-GMT
 
3975
****************************************************************************/
 
3976
void put_long_date(char *p,time_t t)
 
3977
{
 
3978
  uint32 tlow,thigh;
 
3979
  double d;
 
3980
 
 
3981
  if (t==0) {
 
3982
    SIVAL(p,0,0); SIVAL(p,4,0);
 
3983
    return;
 
3984
  }
 
3985
 
 
3986
  /* this converts GMT to kludge-GMT */
 
3987
  t -= TimeDiff(t) - serverzone; 
 
3988
 
 
3989
  d = (double) (t);
 
3990
 
 
3991
  d += TIME_FIXUP_CONSTANT;
 
3992
 
 
3993
  d *= 1.0e7;
 
3994
 
 
3995
  thigh = (uint32)(d * (1.0/(4.0*(double)(1<<30))));
 
3996
  tlow = (uint32)(d - ((double)thigh)*4.0*(double)(1<<30));
 
3997
 
 
3998
  SIVAL(p,0,tlow);
 
3999
  SIVAL(p,4,thigh);
 
4000
}
 
4001
 
 
4002
/*******************************************************************
 
4003
sub strings with useful parameters
 
4004
********************************************************************/
 
4005
void standard_sub_basic(char *s)
 
4006
{
 
4007
  if (!strchr(s,'%')) return;
 
4008
 
 
4009
  string_sub(s,"%R",remote_proto);
 
4010
  string_sub(s,"%a",remote_arch);
 
4011
  string_sub(s,"%m",remote_machine);
 
4012
  string_sub(s,"%L",local_machine);
 
4013
 
 
4014
  if (!strchr(s,'%')) return;
 
4015
 
 
4016
  string_sub(s,"%v",VERSION);
 
4017
  string_sub(s,"%h",myhostname);
 
4018
  string_sub(s,"%U",sesssetup_user);
 
4019
 
 
4020
  if (!strchr(s,'%')) return;
 
4021
 
 
4022
  string_sub(s,"%I",Client_info.addr);
 
4023
  string_sub(s,"%M",Client_info.name);
 
4024
  string_sub(s,"%T",timestring());
 
4025
 
 
4026
  if (!strchr(s,'%')) return;
 
4027
 
 
4028
  {
 
4029
    char pidstr[10];
 
4030
    sprintf(pidstr,"%d",(int)getpid());
 
4031
    string_sub(s,"%d",pidstr);
 
4032
  }
 
4033
}
 
4034
 
 
4035
 
 
4036
/*******************************************************************
 
4037
write a string in unicoode format
 
4038
********************************************************************/
 
4039
void PutUniCode(char *dst,char *src)
 
4040
{
 
4041
  while (*src) {
 
4042
    dst[0] = src[0];
 
4043
    dst[1] = 0;    
 
4044
    dst += 2;
 
4045
    src++;
 
4046
  }
 
4047
  dst[0] = dst[1] = 0;
 
4048
}
 
4049
 
 
4050
 
 
4051
/****************************************************************************
 
4052
a wrapper for gethostbyname() that tries with all lower and all upper case 
 
4053
if the initial name fails
 
4054
****************************************************************************/
 
4055
struct hostent *Get_Hostbyname(char *name)
 
4056
{
 
4057
  char *name2 = strdup(name);
 
4058
  struct hostent *ret;
 
4059
 
 
4060
  if (!name2)
 
4061
    {
 
4062
      DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
 
4063
      exit(0);
 
4064
    }
 
4065
 
 
4066
  if (!isalnum(*name2))
 
4067
    {
 
4068
      free(name2);
 
4069
      return(NULL);
 
4070
    }
 
4071
 
 
4072
#ifdef GH_SLEAZE
 
4073
  signal (SIGALRM, tmx);
 
4074
  alarm (5);
 
4075
  if (setjmp (gh_buf) > 0)
 
4076
    return (NULL);
 
4077
#endif
 
4078
  ret = gethostbyname(name2);
 
4079
#ifdef GH_SLEAZE
 
4080
  signal (SIGALRM, SIG_DFL);
 
4081
  alarm (0);
 
4082
#endif
 
4083
  if (ret != NULL)
 
4084
    {
 
4085
      free(name2);
 
4086
      return(ret);
 
4087
    }
 
4088
 
 
4089
  /* try with all lowercase */
 
4090
  strlower(name2);
 
4091
  ret = gethostbyname(name2);
 
4092
  if (ret != NULL)
 
4093
    {
 
4094
      free(name2);
 
4095
      return(ret);
 
4096
    }
 
4097
 
 
4098
  /* try with all uppercase */
 
4099
  strupper(name2);
 
4100
  ret = gethostbyname(name2);
 
4101
  if (ret != NULL)
 
4102
    {
 
4103
      free(name2);
 
4104
      return(ret);
 
4105
    }
 
4106
  
 
4107
  /* nothing works :-( */
 
4108
  free(name2);
 
4109
  return(NULL);
 
4110
}
 
4111
 
 
4112
 
 
4113
/****************************************************************************
 
4114
check if a process exists. Does this work on all unixes?
 
4115
****************************************************************************/
 
4116
BOOL process_exists(int pid)
 
4117
{
 
4118
#ifdef LINUX
 
4119
  fstring s;
 
4120
  sprintf(s,"/proc/%d",pid);
 
4121
  return(directory_exist(s,NULL));
 
4122
#else
 
4123
  {
 
4124
    static BOOL tested=False;
 
4125
    static BOOL ok=False;
 
4126
    fstring s;
 
4127
    if (!tested) {
 
4128
      tested = True;
 
4129
      sprintf(s,"/proc/%05d",getpid());
 
4130
      ok = file_exist(s,NULL);
 
4131
    }
 
4132
    if (ok) {
 
4133
      sprintf(s,"/proc/%05d",pid);
 
4134
      return(file_exist(s,NULL));
 
4135
    }
 
4136
  }
 
4137
 
 
4138
  /* a best guess for non root access */
 
4139
  if (geteuid() != 0) return(True);
 
4140
 
 
4141
  /* otherwise use kill */
 
4142
  return(pid == getpid() || kill(pid,0) == 0);
 
4143
#endif
 
4144
}
 
4145
 
 
4146
 
 
4147
/*******************************************************************
 
4148
turn a uid into a user name
 
4149
********************************************************************/
 
4150
char *uidtoname(int uid)
 
4151
{
 
4152
  static char name[20];
 
4153
  struct passwd *pass = getpwuid(uid);
 
4154
  if (pass) return(pass->pw_name);
 
4155
  sprintf(name,"%d",uid);
 
4156
  return(name);
 
4157
}
 
4158
 
 
4159
/*******************************************************************
 
4160
turn a gid into a group name
 
4161
********************************************************************/
 
4162
char *gidtoname(int gid)
 
4163
{
 
4164
  static char name[20];
 
4165
  struct group *grp = getgrgid(gid);
 
4166
  if (grp) return(grp->gr_name);
 
4167
  sprintf(name,"%d",gid);
 
4168
  return(name);
 
4169
}
 
4170
 
 
4171
/*******************************************************************
 
4172
block sigs
 
4173
********************************************************************/
 
4174
void BlockSignals(BOOL block)
 
4175
{
 
4176
#ifdef USE_SIGBLOCK
 
4177
  int block_mask = (sigmask(SIGTERM)|sigmask(SIGQUIT)|sigmask(SIGSEGV)
 
4178
                    |sigmask(SIGCHLD)|sigmask(SIGQUIT)|sigmask(SIGBUS)|
 
4179
                    sigmask(SIGINT));
 
4180
  if (block) 
 
4181
    sigblock(block_mask);
 
4182
  else
 
4183
    sigunblock(block_mask);
 
4184
#endif
 
4185
}
 
4186
 
 
4187
#ifdef USE_DIRECT
 
4188
#define DIRECT direct
 
4189
#else
 
4190
#define DIRECT dirent
 
4191
#endif
 
4192
 
 
4193
/*******************************************************************
 
4194
a readdir wrapper which just returns the file name
 
4195
also return the inode number if requested
 
4196
********************************************************************/
 
4197
char *readdirname(void *p)
 
4198
{
 
4199
  struct DIRECT *ptr;
 
4200
  char *dname;
 
4201
 
 
4202
  if (!p) return(NULL);
 
4203
  
 
4204
  ptr = (struct DIRECT *)readdir(p);
 
4205
  if (!ptr) return(NULL);
 
4206
 
 
4207
  dname = ptr->d_name;
 
4208
 
 
4209
#ifdef KANJI
 
4210
  {
 
4211
    static pstring buf;
 
4212
    strcpy(buf, dname);
 
4213
    unix_to_dos(buf, True);
 
4214
    dname = buf;
 
4215
  }
 
4216
#endif
 
4217
 
 
4218
#ifdef NEXT2
 
4219
  if (telldir(p) < 0) return(NULL);
 
4220
#endif
 
4221
 
 
4222
#ifdef SUNOS5
 
4223
  /* this handles a broken compiler setup, causing a mixture
 
4224
   of BSD and SYSV headers and libraries */
 
4225
  {
 
4226
    static BOOL broken_readdir = False;
 
4227
    if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
 
4228
      {
 
4229
        DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
 
4230
        broken_readdir = True;
 
4231
      }
 
4232
    if (broken_readdir)
 
4233
      return(dname-2);
 
4234
  }
 
4235
#endif
 
4236
 
 
4237
  return(dname);
 
4238
}
 
4239
 
 
4240
 
 
4241
 
 
4242
#if (defined(SecureWare) && defined(SCO))
 
4243
/* This is needed due to needing the nap() function but we don't want
 
4244
   to include the Xenix libraries since that will break other things...
 
4245
   BTW: system call # 0x0c28 is the same as calling nap() */
 
4246
long nap(long milliseconds) {
 
4247
  return syscall(0x0c28, milliseconds);
 
4248
}
 
4249
#endif
 
4250
 
 
4251
#ifdef NO_INITGROUPS
 
4252
#include <sys/types.h>
 
4253
#include <limits.h>
 
4254
#include <grp.h>
 
4255
 
 
4256
#ifndef NULL
 
4257
#define NULL (void *)0
 
4258
#endif
 
4259
 
 
4260
/****************************************************************************
 
4261
 some systems don't have an initgroups call 
 
4262
****************************************************************************/
 
4263
int initgroups(char *name,gid_t id)
 
4264
{
 
4265
#ifdef NO_SETGROUPS
 
4266
  /* yikes! no SETGROUPS or INITGROUPS? how can this work? */
 
4267
  return(0);
 
4268
#else
 
4269
  gid_t  grouplst[NGROUPS_MAX];
 
4270
  int    i,j;
 
4271
  struct group *g;
 
4272
  char   *gr;
 
4273
 
 
4274
  grouplst[0] = id;
 
4275
  i = 1;
 
4276
  while (i < NGROUPS_MAX && 
 
4277
         ((g = (struct group *)getgrent()) != (struct group *)NULL)) 
 
4278
    {
 
4279
      if (g->gr_gid == id)
 
4280
        continue;
 
4281
      j = 0;
 
4282
      gr = g->gr_mem[0];
 
4283
      while (gr && (*gr != (char)NULL)) {
 
4284
        if (strcmp(name,gr) == 0) {
 
4285
          grouplst[i] = g->gr_gid;
 
4286
          i++;
 
4287
          gr = (char *)NULL;
 
4288
          break;
 
4289
        }
 
4290
        gr = g->gr_mem[++j];
 
4291
      }
 
4292
    }
 
4293
  endgrent();
 
4294
  return(setgroups(i,grouplst));
 
4295
#endif
 
4296
}
 
4297
#endif
 
4298
 
 
4299
 
 
4300
#if WRAP_MALLOC
 
4301
 
 
4302
/* undo the wrapping temporarily */
 
4303
#undef malloc
 
4304
#undef realloc
 
4305
#undef free
 
4306
 
 
4307
/****************************************************************************
 
4308
wrapper for malloc() to catch memory errors
 
4309
****************************************************************************/
 
4310
void *malloc_wrapped(int size,char *file,int line)
 
4311
{
 
4312
#ifdef xx_old_malloc
 
4313
  void *res = xx_old_malloc(size);
 
4314
#else
 
4315
  void *res = malloc(size);
 
4316
#endif
 
4317
  DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
 
4318
        file,line,
 
4319
        size,(unsigned int)res));
 
4320
  return(res);
 
4321
}
 
4322
 
 
4323
/****************************************************************************
 
4324
wrapper for realloc() to catch memory errors
 
4325
****************************************************************************/
 
4326
void *realloc_wrapped(void *ptr,int size,char *file,int line)
 
4327
{
 
4328
#ifdef xx_old_realloc
 
4329
  void *res = xx_old_realloc(ptr,size);
 
4330
#else
 
4331
  void *res = realloc(ptr,size);
 
4332
#endif
 
4333
  DEBUG(3,("Realloc\n"));
 
4334
  DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
 
4335
        file,line,
 
4336
        (unsigned int)ptr));
 
4337
  DEBUG(3,("Malloc called from %s(%d) with size=%d gave ptr=0x%X\n",
 
4338
        file,line,
 
4339
        size,(unsigned int)res));
 
4340
  return(res);
 
4341
}
 
4342
 
 
4343
/****************************************************************************
 
4344
wrapper for free() to catch memory errors
 
4345
****************************************************************************/
 
4346
void free_wrapped(void *ptr,char *file,int line)
 
4347
{
 
4348
#ifdef xx_old_free
 
4349
  xx_old_free(ptr);
 
4350
#else
 
4351
  free(ptr);
 
4352
#endif
 
4353
  DEBUG(3,("free called from %s(%d) with ptr=0x%X\n",
 
4354
        file,line,(unsigned int)ptr));
 
4355
  return;
 
4356
}
 
4357
 
 
4358
/* and re-do the define for spots lower in this file */
 
4359
#define malloc(size) malloc_wrapped(size,__FILE__,__LINE__)
 
4360
#define realloc(ptr,size) realloc_wrapped(ptr,size,__FILE__,__LINE__)
 
4361
#define free(ptr) free_wrapped(ptr,__FILE__,__LINE__)
 
4362
 
 
4363
#endif
 
4364
 
 
4365
#ifdef REPLACE_STRSTR
 
4366
/****************************************************************************
 
4367
Mips version of strstr doesn't seem to work correctly.
 
4368
There is a #define in includes.h to redirect calls to this function.
 
4369
****************************************************************************/
 
4370
char *Strstr(char *s, char *p)
 
4371
{
 
4372
        int len = strlen(p);
 
4373
 
 
4374
        while ( *s != '\0' ) {
 
4375
                if ( strncmp(s, p, len) == 0 )
 
4376
                return s;
 
4377
                s++;
 
4378
        }
 
4379
 
 
4380
        return NULL;
 
4381
}
 
4382
#endif /* REPLACE_STRSTR */
 
4383
 
 
4384
 
 
4385
#ifdef REPLACE_MKTIME
 
4386
/*******************************************************************
 
4387
a mktime() replacement for those who don't have it - contributed by 
 
4388
C.A. Lademann <cal@zls.com>
 
4389
********************************************************************/
 
4390
#define  MINUTE  60
 
4391
#define  HOUR    60*MINUTE
 
4392
#define  DAY             24*HOUR
 
4393
#define  YEAR    365*DAY
 
4394
time_t Mktime(struct tm      *t)
 
4395
{
 
4396
  struct tm       *u;
 
4397
  time_t  epoch = 0;
 
4398
  int             mon [] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
 
4399
  y, m, i;
 
4400
 
 
4401
  if(t->tm_year < 70)
 
4402
    return((time_t)-1);
 
4403
 
 
4404
  epoch = (t->tm_year - 70) * YEAR + 
 
4405
    (t->tm_year / 4 - 70 / 4 - t->tm_year / 100) * DAY;
 
4406
 
 
4407
  y = t->tm_year;
 
4408
  m = 0;
 
4409
 
 
4410
  for(i = 0; i < t->tm_mon; i++) {
 
4411
    epoch += mon [m] * DAY;
 
4412
    if(m == 1 && y % 4 == 0 && (y % 100 != 0 || y % 400 == 0))
 
4413
      epoch += DAY;
 
4414
    
 
4415
    if(++m > 11) {
 
4416
      m = 0;
 
4417
      y++;
 
4418
    }
 
4419
  }
 
4420
 
 
4421
  epoch += (t->tm_mday - 1) * DAY;
 
4422
  epoch += t->tm_hour * HOUR + t->tm_min * MINUTE + t->tm_sec;
 
4423
  
 
4424
  if((u = localtime(&epoch)) != NULL) {
 
4425
    t->tm_sec = u->tm_sec;
 
4426
    t->tm_min = u->tm_min;
 
4427
    t->tm_hour = u->tm_hour;
 
4428
    t->tm_mday = u->tm_mday;
 
4429
    t->tm_mon = u->tm_mon;
 
4430
    t->tm_year = u->tm_year;
 
4431
    t->tm_wday = u->tm_wday;
 
4432
    t->tm_yday = u->tm_yday;
 
4433
    t->tm_isdst = u->tm_isdst;
 
4434
#ifndef NO_TM_NAME
 
4435
    memcpy(t->tm_name, u->tm_name, LTZNMAX);
 
4436
#endif
 
4437
  }
 
4438
 
 
4439
  return(epoch);
 
4440
}
 
4441
#endif /* REPLACE_MKTIME */
 
4442
 
 
4443
 
 
4444
 
 
4445
#ifdef REPLACE_RENAME
 
4446
/* Rename a file. (from libiberty in GNU binutils)  */
 
4447
int
 
4448
rename (zfrom, zto)
 
4449
     const char *zfrom;
 
4450
     const char *zto;
 
4451
{
 
4452
  if (link (zfrom, zto) < 0)
 
4453
    {
 
4454
      if (errno != EEXIST)
 
4455
        return -1;
 
4456
      if (unlink (zto) < 0
 
4457
          || link (zfrom, zto) < 0)
 
4458
        return -1;
 
4459
    }
 
4460
  return unlink (zfrom);
 
4461
}
 
4462
#endif
 
4463
 
 
4464
 
 
4465
#ifdef REPLACE_INNETGR
 
4466
/*
 
4467
 * Search for a match in a netgroup. This replaces it on broken systems.
 
4468
 */
 
4469
int InNetGr(group, host, user, dom)
 
4470
        char *group, *host, *user, *dom;
 
4471
{
 
4472
  char *hst, *usr, *dm;
 
4473
  
 
4474
  setnetgrent(group);
 
4475
  while (getnetgrent(&hst, &usr, &dm))
 
4476
    if (((host == 0) || (hst == 0) || !strcmp(host, hst)) &&
 
4477
        ((user == 0) || (usr == 0) || !strcmp(user, usr)) &&
 
4478
        ((dom == 0) || (dm == 0) || !strcmp(dom, dm))) {
 
4479
      endnetgrent();
 
4480
      return (1);
 
4481
    }
 
4482
  endnetgrent();
 
4483
  return (0);
 
4484
}
 
4485
#endif
 
4486
 
 
4487
 
 
4488
#if WRAP_MEMCPY
 
4489
#undef memcpy
 
4490
/*******************************************************************
 
4491
a wrapper around memcpy for diagnostic purposes
 
4492
********************************************************************/
 
4493
void *memcpy_wrapped(void *d,void *s,int l,char *fname,int line)
 
4494
{
 
4495
  if (l>64 && (((int)d)%4) != (((int)s)%4))
 
4496
    DEBUG(4,("Misaligned memcpy(0x%X,0x%X,%d) at %s(%d)\n",d,s,l,fname,line));
 
4497
#ifdef xx_old_memcpy  
 
4498
  return(xx_old_memcpy(d,s,l));
 
4499
#else
 
4500
  return(memcpy(d,s,l));
 
4501
#endif
 
4502
}
 
4503
#define memcpy(d,s,l) memcpy_wrapped(d,s,l,__FILE__,__LINE__)
 
4504
#endif
 
4505
 
 
4506
 
 
4507