Kanji fixes for upper/lower case conversion with sjis characters.
[Samba/ekacnet.git] / source / lib / util.c
blob6f6e03fbd60f0b813ffc16f9d27a3e5f7ba09e9f
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
5 Copyright (C) Andrew Tridgell 1992-1997
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "includes.h"
24 pstring scope = "";
26 int DEBUGLEVEL = 1;
28 BOOL passive = False;
30 int Protocol = PROTOCOL_COREPLUS;
32 /* a default finfo structure to ensure all fields are sensible */
33 file_info def_finfo = {-1,0,0,0,0,0,0,""};
35 /* these are some file handles where debug info will be stored */
36 FILE *dbf = NULL;
38 /* the client file descriptor */
39 int Client = -1;
41 /* the last IP received from */
42 struct in_addr lastip;
44 /* the last port received from */
45 int lastport=0;
47 /* this is used by the chaining code */
48 int chain_size = 0;
50 int trans_num = 0;
53 case handling on filenames
55 int case_default = CASE_LOWER;
57 pstring debugf = "";
58 int syslog_level;
60 /* the following control case operations - they are put here so the
61 client can link easily */
62 BOOL case_sensitive;
63 BOOL case_preserve;
64 BOOL use_mangled_map = False;
65 BOOL short_case_preserve;
66 BOOL case_mangle;
68 fstring remote_machine="";
69 fstring local_machine="";
70 fstring remote_arch="UNKNOWN";
71 fstring remote_proto="UNKNOWN";
72 pstring myhostname="";
73 pstring user_socket_options="";
74 pstring sesssetup_user="";
75 pstring myname = "";
76 fstring myworkgroup = "";
77 char **my_netbios_names;
79 int smb_read_error = 0;
81 static BOOL stdout_logging = False;
83 static char *filename_dos(char *path,char *buf);
85 /*******************************************************************
86 get ready for syslog stuff
87 ******************************************************************/
88 void setup_logging(char *pname,BOOL interactive)
90 #ifdef SYSLOG
91 if (!interactive) {
92 char *p = strrchr(pname,'/');
93 if (p) pname = p+1;
94 openlog(pname, LOG_PID, LOG_DAEMON);
96 #endif
97 if (interactive) {
98 stdout_logging = True;
99 dbf = stdout;
104 BOOL append_log=False;
107 /****************************************************************************
108 reopen the log files
109 ****************************************************************************/
110 void reopen_logs(void)
112 extern FILE *dbf;
113 pstring fname;
115 if (DEBUGLEVEL > 0)
117 strcpy(fname,debugf);
118 if (lp_loaded() && (*lp_logfile()))
119 strcpy(fname,lp_logfile());
121 if (!strcsequal(fname,debugf) || !dbf || !file_exist(debugf,NULL))
123 int oldumask = umask(022);
124 strcpy(debugf,fname);
125 if (dbf) fclose(dbf);
126 if (append_log)
127 dbf = fopen(debugf,"a");
128 else
129 dbf = fopen(debugf,"w");
130 if (dbf) setbuf(dbf,NULL);
131 umask(oldumask);
134 else
136 if (dbf)
138 fclose(dbf);
139 dbf = NULL;
145 /*******************************************************************
146 check if the log has grown too big
147 ********************************************************************/
148 static void check_log_size(void)
150 static int debug_count=0;
151 int maxlog;
152 struct stat st;
154 if (debug_count++ < 100) return;
156 maxlog = lp_max_log_size() * 1024;
157 if (!dbf || maxlog <= 0) return;
159 if (fstat(fileno(dbf),&st) == 0 && st.st_size > maxlog) {
160 fclose(dbf); dbf = NULL;
161 reopen_logs();
162 if (dbf && file_size(debugf) > maxlog) {
163 pstring name;
164 fclose(dbf); dbf = NULL;
165 sprintf(name,"%s.old",debugf);
166 sys_rename(debugf,name);
167 reopen_logs();
170 debug_count=0;
174 /*******************************************************************
175 write an debug message on the debugfile. This is called by the DEBUG
176 macro
177 ********************************************************************/
178 #ifdef __STDC__
179 int Debug1(char *format_str, ...)
181 #else
182 int Debug1(va_alist)
183 va_dcl
185 char *format_str;
186 #endif
187 va_list ap;
189 if (stdout_logging) {
190 #ifdef __STDC__
191 va_start(ap, format_str);
192 #else
193 va_start(ap);
194 format_str = va_arg(ap,char *);
195 #endif
196 vfprintf(dbf,format_str,ap);
197 va_end(ap);
198 return(0);
201 #ifdef SYSLOG
202 if (!lp_syslog_only())
203 #endif
205 if (!dbf)
207 int oldumask = umask(022);
208 dbf = fopen(debugf,"w");
209 umask(oldumask);
210 if (dbf)
211 setbuf(dbf,NULL);
212 else
213 return(0);
217 #ifdef SYSLOG
218 if (syslog_level < lp_syslog())
221 * map debug levels to syslog() priorities
222 * note that not all DEBUG(0, ...) calls are
223 * necessarily errors
225 static int priority_map[] = {
226 LOG_ERR, /* 0 */
227 LOG_WARNING, /* 1 */
228 LOG_NOTICE, /* 2 */
229 LOG_INFO, /* 3 */
231 int priority;
232 pstring msgbuf;
234 if (syslog_level >= sizeof(priority_map) / sizeof(priority_map[0]) ||
235 syslog_level < 0)
236 priority = LOG_DEBUG;
237 else
238 priority = priority_map[syslog_level];
240 #ifdef __STDC__
241 va_start(ap, format_str);
242 #else
243 va_start(ap);
244 format_str = va_arg(ap,char *);
245 #endif
246 vsprintf(msgbuf, format_str, ap);
247 va_end(ap);
249 msgbuf[255] = '\0';
250 syslog(priority, "%s", msgbuf);
252 #endif
254 #ifdef SYSLOG
255 if (!lp_syslog_only())
256 #endif
258 #ifdef __STDC__
259 va_start(ap, format_str);
260 #else
261 va_start(ap);
262 format_str = va_arg(ap,char *);
263 #endif
264 vfprintf(dbf,format_str,ap);
265 va_end(ap);
266 fflush(dbf);
269 check_log_size();
271 return(0);
274 /****************************************************************************
275 find a suitable temporary directory. The result should be copied immediately
276 as it may be overwritten by a subsequent call
277 ****************************************************************************/
278 char *tmpdir(void)
280 char *p;
281 if ((p = getenv("TMPDIR"))) {
282 return p;
284 return "/tmp";
289 /****************************************************************************
290 determine if a file descriptor is in fact a socket
291 ****************************************************************************/
292 BOOL is_a_socket(int fd)
294 int v,l;
295 l = sizeof(int);
296 return(getsockopt(fd, SOL_SOCKET, SO_TYPE, (char *)&v, &l) == 0);
300 static char *last_ptr=NULL;
302 /****************************************************************************
303 Get the next token from a string, return False if none found
304 handles double-quotes.
305 Based on a routine by GJC@VILLAGE.COM.
306 Extensively modified by Andrew.Tridgell@anu.edu.au
307 ****************************************************************************/
308 BOOL next_token(char **ptr,char *buff,char *sep)
310 char *s;
311 BOOL quoted;
313 if (!ptr) ptr = &last_ptr;
314 if (!ptr) return(False);
316 s = *ptr;
318 /* default to simple separators */
319 if (!sep) sep = " \t\n\r";
321 /* find the first non sep char */
322 while(*s && strchr(sep,*s)) s++;
324 /* nothing left? */
325 if (! *s) return(False);
327 /* copy over the token */
328 for (quoted = False; *s && (quoted || !strchr(sep,*s)); s++)
330 if (*s == '\"')
331 quoted = !quoted;
332 else
333 *buff++ = *s;
336 *ptr = (*s) ? s+1 : s;
337 *buff = 0;
338 last_ptr = *ptr;
340 return(True);
343 /****************************************************************************
344 Convert list of tokens to array; dependent on above routine.
345 Uses last_ptr from above - bit of a hack.
346 ****************************************************************************/
347 char **toktocliplist(int *ctok, char *sep)
349 char *s=last_ptr;
350 int ictok=0;
351 char **ret, **iret;
353 if (!sep) sep = " \t\n\r";
355 while(*s && strchr(sep,*s)) s++;
357 /* nothing left? */
358 if (!*s) return(NULL);
360 do {
361 ictok++;
362 while(*s && (!strchr(sep,*s))) s++;
363 while(*s && strchr(sep,*s)) *s++=0;
364 } while(*s);
366 *ctok=ictok;
367 s=last_ptr;
369 if (!(ret=iret=malloc(ictok*sizeof(char *)))) return NULL;
371 while(ictok--) {
372 *iret++=s;
373 while(*s++);
374 while(!*s) s++;
377 return ret;
380 #ifndef HAVE_MEMMOVE
381 /*******************************************************************
382 safely copies memory, ensuring no overlap problems.
383 this is only used if the machine does not have it's own memmove().
384 this is not the fastest algorithm in town, but it will do for our
385 needs.
386 ********************************************************************/
387 void *MemMove(void *dest,void *src,int size)
389 unsigned long d,s;
390 int i;
391 if (dest==src || !size) return(dest);
393 d = (unsigned long)dest;
394 s = (unsigned long)src;
396 if ((d >= (s+size)) || (s >= (d+size))) {
397 /* no overlap */
398 memcpy(dest,src,size);
399 return(dest);
402 if (d < s)
404 /* we can forward copy */
405 if (s-d >= sizeof(int) &&
406 !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
407 /* do it all as words */
408 int *idest = (int *)dest;
409 int *isrc = (int *)src;
410 size /= sizeof(int);
411 for (i=0;i<size;i++) idest[i] = isrc[i];
412 } else {
413 /* simplest */
414 char *cdest = (char *)dest;
415 char *csrc = (char *)src;
416 for (i=0;i<size;i++) cdest[i] = csrc[i];
419 else
421 /* must backward copy */
422 if (d-s >= sizeof(int) &&
423 !(s%sizeof(int)) && !(d%sizeof(int)) && !(size%sizeof(int))) {
424 /* do it all as words */
425 int *idest = (int *)dest;
426 int *isrc = (int *)src;
427 size /= sizeof(int);
428 for (i=size-1;i>=0;i--) idest[i] = isrc[i];
429 } else {
430 /* simplest */
431 char *cdest = (char *)dest;
432 char *csrc = (char *)src;
433 for (i=size-1;i>=0;i--) cdest[i] = csrc[i];
436 return(dest);
438 #endif
441 /****************************************************************************
442 prompte a dptr (to make it recently used)
443 ****************************************************************************/
444 void array_promote(char *array,int elsize,int element)
446 char *p;
447 if (element == 0)
448 return;
450 p = (char *)malloc(elsize);
452 if (!p)
454 DEBUG(5,("Ahh! Can't malloc\n"));
455 return;
457 memcpy(p,array + element * elsize, elsize);
458 memmove(array + elsize,array,elsize*element);
459 memcpy(array,p,elsize);
460 free(p);
463 enum SOCK_OPT_TYPES {OPT_BOOL,OPT_INT,OPT_ON};
465 struct
467 char *name;
468 int level;
469 int option;
470 int value;
471 int opttype;
472 } socket_options[] = {
473 {"SO_KEEPALIVE", SOL_SOCKET, SO_KEEPALIVE, 0, OPT_BOOL},
474 {"SO_REUSEADDR", SOL_SOCKET, SO_REUSEADDR, 0, OPT_BOOL},
475 {"SO_BROADCAST", SOL_SOCKET, SO_BROADCAST, 0, OPT_BOOL},
476 #ifdef TCP_NODELAY
477 {"TCP_NODELAY", IPPROTO_TCP, TCP_NODELAY, 0, OPT_BOOL},
478 #endif
479 #ifdef IPTOS_LOWDELAY
480 {"IPTOS_LOWDELAY", IPPROTO_IP, IP_TOS, IPTOS_LOWDELAY, OPT_ON},
481 #endif
482 #ifdef IPTOS_THROUGHPUT
483 {"IPTOS_THROUGHPUT", IPPROTO_IP, IP_TOS, IPTOS_THROUGHPUT, OPT_ON},
484 #endif
485 #ifdef SO_SNDBUF
486 {"SO_SNDBUF", SOL_SOCKET, SO_SNDBUF, 0, OPT_INT},
487 #endif
488 #ifdef SO_RCVBUF
489 {"SO_RCVBUF", SOL_SOCKET, SO_RCVBUF, 0, OPT_INT},
490 #endif
491 #ifdef SO_SNDLOWAT
492 {"SO_SNDLOWAT", SOL_SOCKET, SO_SNDLOWAT, 0, OPT_INT},
493 #endif
494 #ifdef SO_RCVLOWAT
495 {"SO_RCVLOWAT", SOL_SOCKET, SO_RCVLOWAT, 0, OPT_INT},
496 #endif
497 #ifdef SO_SNDTIMEO
498 {"SO_SNDTIMEO", SOL_SOCKET, SO_SNDTIMEO, 0, OPT_INT},
499 #endif
500 #ifdef SO_RCVTIMEO
501 {"SO_RCVTIMEO", SOL_SOCKET, SO_RCVTIMEO, 0, OPT_INT},
502 #endif
503 {NULL,0,0,0,0}};
507 /****************************************************************************
508 set user socket options
509 ****************************************************************************/
510 void set_socket_options(int fd, char *options)
512 string tok;
514 while (next_token(&options,tok," \t,"))
516 int ret=0,i;
517 int value = 1;
518 char *p;
519 BOOL got_value = False;
521 if ((p = strchr(tok,'=')))
523 *p = 0;
524 value = atoi(p+1);
525 got_value = True;
528 for (i=0;socket_options[i].name;i++)
529 if (strequal(socket_options[i].name,tok))
530 break;
532 if (!socket_options[i].name)
534 DEBUG(0,("Unknown socket option %s\n",tok));
535 continue;
538 switch (socket_options[i].opttype)
540 case OPT_BOOL:
541 case OPT_INT:
542 ret = setsockopt(fd,socket_options[i].level,
543 socket_options[i].option,(char *)&value,sizeof(int));
544 break;
546 case OPT_ON:
547 if (got_value)
548 DEBUG(0,("syntax error - %s does not take a value\n",tok));
551 int on = socket_options[i].value;
552 ret = setsockopt(fd,socket_options[i].level,
553 socket_options[i].option,(char *)&on,sizeof(int));
555 break;
558 if (ret != 0)
559 DEBUG(0,("Failed to set socket option %s\n",tok));
565 /****************************************************************************
566 close the socket communication
567 ****************************************************************************/
568 void close_sockets(void )
570 close(Client);
571 Client = 0;
574 /****************************************************************************
575 determine whether we are in the specified group
576 ****************************************************************************/
577 BOOL in_group(gid_t group, int current_gid, int ngroups, int *groups)
579 int i;
581 if (group == current_gid) return(True);
583 for (i=0;i<ngroups;i++)
584 if (group == groups[i])
585 return(True);
587 return(False);
590 /****************************************************************************
591 this is a safer strcpy(), meant to prevent core dumps when nasty things happen
592 ****************************************************************************/
593 char *StrCpy(char *dest,char *src)
595 char *d = dest;
597 #if AJT
598 /* I don't want to get lazy with these ... */
599 if (!dest || !src) {
600 DEBUG(0,("ERROR: NULL StrCpy() called!\n"));
601 ajt_panic();
603 #endif
605 if (!dest) return(NULL);
606 if (!src) {
607 *dest = 0;
608 return(dest);
610 while ((*d++ = *src++)) ;
611 return(dest);
614 /****************************************************************************
615 line strncpy but always null terminates. Make sure there is room!
616 ****************************************************************************/
617 char *StrnCpy(char *dest,char *src,int n)
619 char *d = dest;
620 if (!dest) return(NULL);
621 if (!src) {
622 *dest = 0;
623 return(dest);
625 while (n-- && (*d++ = *src++)) ;
626 *d = 0;
627 return(dest);
631 /*******************************************************************
632 copy an IP address from one buffer to another
633 ********************************************************************/
634 void putip(void *dest,void *src)
636 memcpy(dest,src,4);
640 /****************************************************************************
641 interpret the weird netbios "name". Return the name type
642 ****************************************************************************/
643 static int name_interpret(char *in,char *out)
645 int ret;
646 int len = (*in++) / 2;
648 *out=0;
650 if (len > 30 || len<1) return(0);
652 while (len--)
654 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P') {
655 *out = 0;
656 return(0);
658 *out = ((in[0]-'A')<<4) + (in[1]-'A');
659 in += 2;
660 out++;
662 *out = 0;
663 ret = out[-1];
665 #ifdef NETBIOS_SCOPE
666 /* Handle any scope names */
667 while(*in)
669 *out++ = '.'; /* Scope names are separated by periods */
670 len = *(unsigned char *)in++;
671 StrnCpy(out, in, len);
672 out += len;
673 *out=0;
674 in += len;
676 #endif
677 return(ret);
680 /****************************************************************************
681 mangle a name into netbios format
682 ****************************************************************************/
683 int name_mangle(char *In,char *Out,char name_type)
685 fstring name;
686 char buf[20];
687 char *in = (char *)&buf[0];
688 char *out = (char *)Out;
689 char *p, *label;
690 int i;
692 if (In[0] != '*') {
693 StrnCpy(name,In,sizeof(name)-1);
694 sprintf(buf,"%-15.15s%c",name,name_type);
695 } else {
696 buf[0]='*';
697 memset(&buf[1],0,16);
700 *out++ = 32;
701 for (i=0;i<16;i++) {
702 char c = toupper(in[i]);
703 out[i*2] = (c>>4) + 'A';
704 out[i*2+1] = (c & 0xF) + 'A';
706 out[32]=0;
707 out += 32;
709 label = scope;
710 while (*label)
712 p = strchr(label, '.');
713 if (p == 0)
714 p = label + strlen(label);
715 *out++ = p - label;
716 memcpy(out, label, p - label);
717 out += p - label;
718 label += p - label + (*p == '.');
720 *out = 0;
721 return(name_len(Out));
725 /*******************************************************************
726 check if a file exists
727 ********************************************************************/
728 BOOL file_exist(char *fname,struct stat *sbuf)
730 struct stat st;
731 if (!sbuf) sbuf = &st;
733 if (sys_stat(fname,sbuf) != 0)
734 return(False);
736 return(S_ISREG(sbuf->st_mode));
739 /*******************************************************************
740 check a files mod time
741 ********************************************************************/
742 time_t file_modtime(char *fname)
744 struct stat st;
746 if (sys_stat(fname,&st) != 0)
747 return(0);
749 return(st.st_mtime);
752 /*******************************************************************
753 check if a directory exists
754 ********************************************************************/
755 BOOL directory_exist(char *dname,struct stat *st)
757 struct stat st2;
758 BOOL ret;
760 if (!st) st = &st2;
762 if (sys_stat(dname,st) != 0)
763 return(False);
765 ret = S_ISDIR(st->st_mode);
766 if(!ret)
767 errno = ENOTDIR;
768 return ret;
771 /*******************************************************************
772 returns the size in bytes of the named file
773 ********************************************************************/
774 uint32 file_size(char *file_name)
776 struct stat buf;
777 buf.st_size = 0;
778 sys_stat(file_name,&buf);
779 return(buf.st_size);
782 /*******************************************************************
783 return a string representing an attribute for a file
784 ********************************************************************/
785 char *attrib_string(int mode)
787 static char attrstr[10];
789 attrstr[0] = 0;
791 if (mode & aVOLID) strcat(attrstr,"V");
792 if (mode & aDIR) strcat(attrstr,"D");
793 if (mode & aARCH) strcat(attrstr,"A");
794 if (mode & aHIDDEN) strcat(attrstr,"H");
795 if (mode & aSYSTEM) strcat(attrstr,"S");
796 if (mode & aRONLY) strcat(attrstr,"R");
798 return(attrstr);
802 /*******************************************************************
803 case insensitive string compararison
804 ********************************************************************/
805 int StrCaseCmp(const char *s, const char *t)
807 /* compare until we run out of string, either t or s, or find a difference */
808 /* We *must* use toupper rather than tolower here due to the
809 asynchronous upper to lower mapping.
811 #ifdef KANJI
812 int diff;
813 for (;;)
815 if (!*s || !*t)
816 return toupper (*s) - toupper (*t);
817 else if (is_sj_alph (*s) && is_sj_alph (*t))
819 diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
820 if (diff)
821 return diff;
822 s += 2;
823 t += 2;
825 else if (is_shift_jis (*s) && is_shift_jis (*t))
827 diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
828 if (diff)
829 return diff;
830 diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
831 if (diff)
832 return diff;
833 s += 2;
834 t += 2;
836 else if (is_shift_jis (*s))
837 return 1;
838 else if (is_shift_jis (*t))
839 return -1;
840 else
842 diff = toupper (*s) - toupper (*t);
843 if (diff)
844 return diff;
845 s++;
846 t++;
849 #else /* KANJI */
850 while (*s && *t && toupper(*s) == toupper(*t))
852 s++; t++;
855 return(toupper(*s) - toupper(*t));
856 #endif /* KANJI */
859 /*******************************************************************
860 case insensitive string compararison, length limited
861 ********************************************************************/
862 int StrnCaseCmp(const char *s, const char *t, int n)
864 /* compare until we run out of string, either t or s, or chars */
865 /* We *must* use toupper rather than tolower here due to the
866 asynchronous upper to lower mapping.
868 #ifdef KANJI
869 int diff;
870 for (;n > 0;)
872 if (!*s || !*t)
873 return toupper (*s) - toupper (*t);
874 else if (is_sj_alph (*s) && is_sj_alph (*t))
876 diff = sj_toupper2 (*(s+1)) - sj_toupper2 (*(t+1));
877 if (diff)
878 return diff;
879 s += 2;
880 t += 2;
881 n -= 2;
883 else if (is_shift_jis (*s) && is_shift_jis (*t))
885 diff = ((int) (unsigned char) *s) - ((int) (unsigned char) *t);
886 if (diff)
887 return diff;
888 diff = ((int) (unsigned char) *(s+1)) - ((int) (unsigned char) *(t+1));
889 if (diff)
890 return diff;
891 s += 2;
892 t += 2;
893 n -= 2;
895 else if (is_shift_jis (*s))
896 return 1;
897 else if (is_shift_jis (*t))
898 return -1;
899 else
901 diff = toupper (*s) - toupper (*t);
902 if (diff)
903 return diff;
904 s++;
905 t++;
906 n--;
909 return 0;
910 #else /* KANJI */
911 while (n-- && *s && *t && toupper(*s) == toupper(*t))
913 s++; t++;
916 /* not run out of chars - strings are different lengths */
917 if (n) return(toupper(*s) - toupper(*t));
919 /* identical up to where we run out of chars, and strings are same length */
920 return(0);
921 #endif /* KANJI */
924 /*******************************************************************
925 compare 2 strings
926 ********************************************************************/
927 BOOL strequal(const char *s1, const char *s2)
929 if (s1 == s2) return(True);
930 if (!s1 || !s2) return(False);
932 return(StrCaseCmp(s1,s2)==0);
935 /*******************************************************************
936 compare 2 strings up to and including the nth char.
937 ******************************************************************/
938 BOOL strnequal(const char *s1,const char *s2,int n)
940 if (s1 == s2) return(True);
941 if (!s1 || !s2 || !n) return(False);
943 return(StrnCaseCmp(s1,s2,n)==0);
946 /*******************************************************************
947 compare 2 strings (case sensitive)
948 ********************************************************************/
949 BOOL strcsequal(char *s1,char *s2)
951 if (s1 == s2) return(True);
952 if (!s1 || !s2) return(False);
954 return(strcmp(s1,s2)==0);
958 /*******************************************************************
959 convert a string to lower case
960 ********************************************************************/
961 void strlower(char *s)
963 while (*s)
965 #ifdef KANJI
966 if (is_shift_jis (*s)) {
967 if (is_sj_upper (s[0], s[1])) {
968 s[1] = sj_tolower2 (s[1]);
970 s += 2;
971 } else if (is_kana (*s)) {
972 s++;
973 } else {
974 if (isupper(*s))
975 *s = tolower(*s);
976 s++;
978 #else /* KANJI */
979 if (isupper(*s))
980 *s = tolower(*s);
981 s++;
982 #endif /* KANJI */
986 /*******************************************************************
987 convert a string to upper case
988 ********************************************************************/
989 void strupper(char *s)
991 while (*s)
993 #ifdef KANJI
994 if (is_shift_jis (*s)) {
995 if (is_sj_lower (s[0], s[1])) {
996 s[1] = sj_toupper2 (s[1]);
998 s += 2;
999 } else if (is_kana (*s)) {
1000 s++;
1001 } else {
1002 if (islower(*s))
1003 *s = toupper(*s);
1004 s++;
1006 #else /* KANJI */
1007 if (islower(*s))
1008 *s = toupper(*s);
1009 s++;
1010 #endif /* KANJI */
1014 /*******************************************************************
1015 convert a string to "normal" form
1016 ********************************************************************/
1017 void strnorm(char *s)
1019 if (case_default == CASE_UPPER)
1020 strupper(s);
1021 else
1022 strlower(s);
1025 /*******************************************************************
1026 check if a string is in "normal" case
1027 ********************************************************************/
1028 BOOL strisnormal(char *s)
1030 if (case_default == CASE_UPPER)
1031 return(!strhaslower(s));
1033 return(!strhasupper(s));
1037 /****************************************************************************
1038 string replace
1039 ****************************************************************************/
1040 void string_replace(char *s,char oldc,char newc)
1042 while (*s)
1044 #ifdef KANJI
1045 if (is_shift_jis (*s)) {
1046 s += 2;
1047 } else if (is_kana (*s)) {
1048 s++;
1049 } else {
1050 if (oldc == *s)
1051 *s = newc;
1052 s++;
1054 #else /* KANJI */
1055 if (oldc == *s)
1056 *s = newc;
1057 s++;
1058 #endif /* KANJI */
1062 /****************************************************************************
1063 make a file into unix format
1064 ****************************************************************************/
1065 void unix_format(char *fname)
1067 pstring namecopy;
1068 string_replace(fname,'\\','/');
1070 if (*fname == '/')
1072 strcpy(namecopy,fname);
1073 strcpy(fname,".");
1074 strcat(fname,namecopy);
1078 /****************************************************************************
1079 make a file into dos format
1080 ****************************************************************************/
1081 void dos_format(char *fname)
1083 string_replace(fname,'/','\\');
1087 /*******************************************************************
1088 show a smb message structure
1089 ********************************************************************/
1090 void show_msg(char *buf)
1092 int i;
1093 int j;
1094 int bcc=0;
1095 if (DEBUGLEVEL < 5)
1096 return;
1098 DEBUG(5,("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
1099 smb_len(buf),
1100 (int)CVAL(buf,smb_com),
1101 (int)CVAL(buf,smb_rcls),
1102 (int)CVAL(buf,smb_reh),
1103 (int)SVAL(buf,smb_err),
1104 (int)CVAL(buf,smb_flg),
1105 (int)SVAL(buf,smb_flg2)));
1106 DEBUG(5,("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
1107 (int)SVAL(buf,smb_tid),
1108 (int)SVAL(buf,smb_pid),
1109 (int)SVAL(buf,smb_uid),
1110 (int)SVAL(buf,smb_mid),
1111 (int)CVAL(buf,smb_wct)));
1112 for (i=0;i<(int)CVAL(buf,smb_wct);i++)
1113 DEBUG(5,("smb_vwv[%d]=%d (0x%X)\n",i,
1114 SVAL(buf,smb_vwv+2*i),SVAL(buf,smb_vwv+2*i)));
1115 bcc = (int)SVAL(buf,smb_vwv+2*(CVAL(buf,smb_wct)));
1116 DEBUG(5,("smb_bcc=%d\n",bcc));
1117 if (DEBUGLEVEL < 10)
1118 return;
1119 for (i = 0; i < MIN(bcc, 256); i += 16)
1121 for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
1124 DEBUG(10,("%2X ",CVAL(smb_buf(buf),i+j)));
1125 if (j == 7) DEBUG(10, (" "));
1128 DEBUG(10,(" "));
1130 for (j = 0; j < 16 && i+j < MIN(bcc,256); j++)
1132 unsigned char c = CVAL(smb_buf(buf),i+j);
1133 if (c < 32 || c > 128) c = '.';
1134 DEBUG(10,("%c",c));
1136 if (j == 7) DEBUG(10, (" "));
1139 DEBUG(10,("\n"));
1143 /*******************************************************************
1144 return the length of an smb packet
1145 ********************************************************************/
1146 int smb_len(char *buf)
1148 return( PVAL(buf,3) | (PVAL(buf,2)<<8) | ((PVAL(buf,1)&1)<<16) );
1151 /*******************************************************************
1152 set the length of an smb packet
1153 ********************************************************************/
1154 void _smb_setlen(char *buf,int len)
1156 buf[0] = 0;
1157 buf[1] = (len&0x10000)>>16;
1158 buf[2] = (len&0xFF00)>>8;
1159 buf[3] = len&0xFF;
1162 /*******************************************************************
1163 set the length and marker of an smb packet
1164 ********************************************************************/
1165 void smb_setlen(char *buf,int len)
1167 _smb_setlen(buf,len);
1169 CVAL(buf,4) = 0xFF;
1170 CVAL(buf,5) = 'S';
1171 CVAL(buf,6) = 'M';
1172 CVAL(buf,7) = 'B';
1175 /*******************************************************************
1176 setup the word count and byte count for a smb message
1177 ********************************************************************/
1178 int set_message(char *buf,int num_words,int num_bytes,BOOL zero)
1180 if (zero)
1181 bzero(buf + smb_size,num_words*2 + num_bytes);
1182 CVAL(buf,smb_wct) = num_words;
1183 SSVAL(buf,smb_vwv + num_words*SIZEOFWORD,num_bytes);
1184 smb_setlen(buf,smb_size + num_words*2 + num_bytes - 4);
1185 return (smb_size + num_words*2 + num_bytes);
1188 /*******************************************************************
1189 return the number of smb words
1190 ********************************************************************/
1191 int smb_numwords(char *buf)
1193 return (CVAL(buf,smb_wct));
1196 /*******************************************************************
1197 return the size of the smb_buf region of a message
1198 ********************************************************************/
1199 int smb_buflen(char *buf)
1201 return(SVAL(buf,smb_vwv0 + smb_numwords(buf)*2));
1204 /*******************************************************************
1205 return a pointer to the smb_buf data area
1206 ********************************************************************/
1207 int smb_buf_ofs(char *buf)
1209 return (smb_size + CVAL(buf,smb_wct)*2);
1212 /*******************************************************************
1213 return a pointer to the smb_buf data area
1214 ********************************************************************/
1215 char *smb_buf(char *buf)
1217 return (buf + smb_buf_ofs(buf));
1220 /*******************************************************************
1221 return the SMB offset into an SMB buffer
1222 ********************************************************************/
1223 int smb_offset(char *p,char *buf)
1225 return(PTR_DIFF(p,buf+4) + chain_size);
1229 /*******************************************************************
1230 skip past some strings in a buffer
1231 ********************************************************************/
1232 char *skip_string(char *buf,int n)
1234 while (n--)
1235 buf += strlen(buf) + 1;
1236 return(buf);
1239 /*******************************************************************
1240 trim the specified elements off the front and back of a string
1241 ********************************************************************/
1242 BOOL trim_string(char *s,char *front,char *back)
1244 BOOL ret = False;
1245 while (front && *front && strncmp(s,front,strlen(front)) == 0)
1247 char *p = s;
1248 ret = True;
1249 while (1)
1251 if (!(*p = p[strlen(front)]))
1252 break;
1253 p++;
1256 while (back && *back && strlen(s) >= strlen(back) &&
1257 (strncmp(s+strlen(s)-strlen(back),back,strlen(back))==0))
1259 ret = True;
1260 s[strlen(s)-strlen(back)] = 0;
1262 return(ret);
1266 /*******************************************************************
1267 reduce a file name, removing .. elements.
1268 ********************************************************************/
1269 void dos_clean_name(char *s)
1271 char *p=NULL;
1273 DEBUG(3,("dos_clean_name [%s]\n",s));
1275 /* remove any double slashes */
1276 string_sub(s, "\\\\", "\\");
1278 while ((p = strstr(s,"\\..\\")) != NULL)
1280 pstring s1;
1282 *p = 0;
1283 strcpy(s1,p+3);
1285 if ((p=strrchr(s,'\\')) != NULL)
1286 *p = 0;
1287 else
1288 *s = 0;
1289 strcat(s,s1);
1292 trim_string(s,NULL,"\\..");
1294 string_sub(s, "\\.\\", "\\");
1297 /*******************************************************************
1298 reduce a file name, removing .. elements.
1299 ********************************************************************/
1300 void unix_clean_name(char *s)
1302 char *p=NULL;
1304 DEBUG(3,("unix_clean_name [%s]\n",s));
1306 /* remove any double slashes */
1307 string_sub(s, "//","/");
1309 /* Remove leading ./ characters */
1310 if(strncmp(s, "./", 2) == 0) {
1311 trim_string(s, "./", NULL);
1312 if(*s == 0)
1313 strcpy(s,"./");
1316 while ((p = strstr(s,"/../")) != NULL)
1318 pstring s1;
1320 *p = 0;
1321 strcpy(s1,p+3);
1323 if ((p=strrchr(s,'/')) != NULL)
1324 *p = 0;
1325 else
1326 *s = 0;
1327 strcat(s,s1);
1330 trim_string(s,NULL,"/..");
1334 /*******************************************************************
1335 a wrapper for the normal chdir() function
1336 ********************************************************************/
1337 int ChDir(char *path)
1339 int res;
1340 static pstring LastDir="";
1342 if (strcsequal(path,".")) return(0);
1344 if (*path == '/' && strcsequal(LastDir,path)) return(0);
1345 DEBUG(3,("chdir to %s\n",path));
1346 res = sys_chdir(path);
1347 if (!res)
1348 strcpy(LastDir,path);
1349 return(res);
1352 /* number of list structures for a caching GetWd function. */
1353 #define MAX_GETWDCACHE (50)
1355 struct
1357 ino_t inode;
1358 dev_t dev;
1359 char *text;
1360 BOOL valid;
1361 } ino_list[MAX_GETWDCACHE];
1363 BOOL use_getwd_cache=True;
1365 /*******************************************************************
1366 return the absolute current directory path
1367 ********************************************************************/
1368 char *GetWd(char *str)
1370 pstring s;
1371 static BOOL getwd_cache_init = False;
1372 struct stat st, st2;
1373 int i;
1375 *s = 0;
1377 if (!use_getwd_cache)
1378 return(sys_getwd(str));
1380 /* init the cache */
1381 if (!getwd_cache_init)
1383 getwd_cache_init = True;
1384 for (i=0;i<MAX_GETWDCACHE;i++)
1386 string_init(&ino_list[i].text,"");
1387 ino_list[i].valid = False;
1391 /* Get the inode of the current directory, if this doesn't work we're
1392 in trouble :-) */
1394 if (stat(".",&st) == -1)
1396 DEBUG(0,("Very strange, couldn't stat \".\"\n"));
1397 return(sys_getwd(str));
1401 for (i=0; i<MAX_GETWDCACHE; i++)
1402 if (ino_list[i].valid)
1405 /* If we have found an entry with a matching inode and dev number
1406 then find the inode number for the directory in the cached string.
1407 If this agrees with that returned by the stat for the current
1408 directory then all is o.k. (but make sure it is a directory all
1409 the same...) */
1411 if (st.st_ino == ino_list[i].inode &&
1412 st.st_dev == ino_list[i].dev)
1414 if (stat(ino_list[i].text,&st2) == 0)
1416 if (st.st_ino == st2.st_ino &&
1417 st.st_dev == st2.st_dev &&
1418 (st2.st_mode & S_IFMT) == S_IFDIR)
1420 strcpy (str, ino_list[i].text);
1422 /* promote it for future use */
1423 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1424 return (str);
1426 else
1428 /* If the inode is different then something's changed,
1429 scrub the entry and start from scratch. */
1430 ino_list[i].valid = False;
1437 /* We don't have the information to hand so rely on traditional methods.
1438 The very slow getcwd, which spawns a process on some systems, or the
1439 not quite so bad getwd. */
1441 if (!sys_getwd(s))
1443 DEBUG(0,("Getwd failed, errno %d\n",errno));
1444 return (NULL);
1447 strcpy(str,s);
1449 DEBUG(5,("GetWd %s, inode %d, dev %x\n",s,(int)st.st_ino,(int)st.st_dev));
1451 /* add it to the cache */
1452 i = MAX_GETWDCACHE - 1;
1453 string_set(&ino_list[i].text,s);
1454 ino_list[i].dev = st.st_dev;
1455 ino_list[i].inode = st.st_ino;
1456 ino_list[i].valid = True;
1458 /* put it at the top of the list */
1459 array_promote((char *)&ino_list[0],sizeof(ino_list[0]),i);
1461 return (str);
1466 /*******************************************************************
1467 reduce a file name, removing .. elements and checking that
1468 it is below dir in the heirachy. This uses GetWd() and so must be run
1469 on the system that has the referenced file system.
1471 widelinks are allowed if widelinks is true
1472 ********************************************************************/
1473 BOOL reduce_name(char *s,char *dir,BOOL widelinks)
1475 #ifndef REDUCE_PATHS
1476 return True;
1477 #else
1478 pstring dir2;
1479 pstring wd;
1480 pstring basename;
1481 pstring newname;
1482 char *p=NULL;
1483 BOOL relative = (*s != '/');
1485 *dir2 = *wd = *basename = *newname = 0;
1487 if (widelinks)
1489 unix_clean_name(s);
1490 /* can't have a leading .. */
1491 if (strncmp(s,"..",2) == 0 && (s[2]==0 || s[2]=='/'))
1493 DEBUG(3,("Illegal file name? (%s)\n",s));
1494 return(False);
1497 if (strlen(s) == 0)
1498 strcpy(s,"./");
1500 return(True);
1503 DEBUG(3,("reduce_name [%s] [%s]\n",s,dir));
1505 /* remove any double slashes */
1506 string_sub(s,"//","/");
1508 strcpy(basename,s);
1509 p = strrchr(basename,'/');
1511 if (!p)
1512 return(True);
1514 if (!GetWd(wd))
1516 DEBUG(0,("couldn't getwd for %s %s\n",s,dir));
1517 return(False);
1520 if (ChDir(dir) != 0)
1522 DEBUG(0,("couldn't chdir to %s\n",dir));
1523 return(False);
1526 if (!GetWd(dir2))
1528 DEBUG(0,("couldn't getwd for %s\n",dir));
1529 ChDir(wd);
1530 return(False);
1534 if (p && (p != basename))
1536 *p = 0;
1537 if (strcmp(p+1,".")==0)
1538 p[1]=0;
1539 if (strcmp(p+1,"..")==0)
1540 *p = '/';
1543 if (ChDir(basename) != 0)
1545 ChDir(wd);
1546 DEBUG(3,("couldn't chdir for %s %s basename=%s\n",s,dir,basename));
1547 return(False);
1550 if (!GetWd(newname))
1552 ChDir(wd);
1553 DEBUG(2,("couldn't get wd for %s %s\n",s,dir2));
1554 return(False);
1557 if (p && (p != basename))
1559 strcat(newname,"/");
1560 strcat(newname,p+1);
1564 int l = strlen(dir2);
1565 if (dir2[l-1] == '/')
1566 l--;
1568 if (strncmp(newname,dir2,l) != 0)
1570 ChDir(wd);
1571 DEBUG(2,("Bad access attempt? s=%s dir=%s newname=%s l=%d\n",s,dir2,newname,l));
1572 return(False);
1575 if (relative)
1577 if (newname[l] == '/')
1578 strcpy(s,newname + l + 1);
1579 else
1580 strcpy(s,newname+l);
1582 else
1583 strcpy(s,newname);
1586 ChDir(wd);
1588 if (strlen(s) == 0)
1589 strcpy(s,"./");
1591 DEBUG(3,("reduced to %s\n",s));
1592 return(True);
1593 #endif
1596 /****************************************************************************
1597 expand some *s
1598 ****************************************************************************/
1599 static void expand_one(char *Mask,int len)
1601 char *p1;
1602 while ((p1 = strchr(Mask,'*')) != NULL)
1604 int lfill = (len+1) - strlen(Mask);
1605 int l1= (p1 - Mask);
1606 pstring tmp;
1607 strcpy(tmp,Mask);
1608 memset(tmp+l1,'?',lfill);
1609 strcpy(tmp + l1 + lfill,Mask + l1 + 1);
1610 strcpy(Mask,tmp);
1614 /****************************************************************************
1615 expand a wildcard expression, replacing *s with ?s
1616 ****************************************************************************/
1617 void expand_mask(char *Mask,BOOL doext)
1619 pstring mbeg,mext;
1620 pstring dirpart;
1621 pstring filepart;
1622 BOOL hasdot = False;
1623 char *p1;
1624 BOOL absolute = (*Mask == '\\');
1626 *mbeg = *mext = *dirpart = *filepart = 0;
1628 /* parse the directory and filename */
1629 if (strchr(Mask,'\\'))
1630 dirname_dos(Mask,dirpart);
1632 filename_dos(Mask,filepart);
1634 strcpy(mbeg,filepart);
1635 if ((p1 = strchr(mbeg,'.')) != NULL)
1637 hasdot = True;
1638 *p1 = 0;
1639 p1++;
1640 strcpy(mext,p1);
1642 else
1644 strcpy(mext,"");
1645 if (strlen(mbeg) > 8)
1647 strcpy(mext,mbeg + 8);
1648 mbeg[8] = 0;
1652 if (*mbeg == 0)
1653 strcpy(mbeg,"????????");
1654 if ((*mext == 0) && doext && !hasdot)
1655 strcpy(mext,"???");
1657 if (strequal(mbeg,"*") && *mext==0)
1658 strcpy(mext,"*");
1660 /* expand *'s */
1661 expand_one(mbeg,8);
1662 if (*mext)
1663 expand_one(mext,3);
1665 strcpy(Mask,dirpart);
1666 if (*dirpart || absolute) strcat(Mask,"\\");
1667 strcat(Mask,mbeg);
1668 strcat(Mask,".");
1669 strcat(Mask,mext);
1671 DEBUG(6,("Mask expanded to [%s]\n",Mask));
1675 /****************************************************************************
1676 does a string have any uppercase chars in it?
1677 ****************************************************************************/
1678 BOOL strhasupper(char *s)
1680 while (*s)
1682 #ifdef KANJI
1683 if (is_shift_jis (*s)) {
1684 s += 2;
1685 } else if (is_kana (*s)) {
1686 s++;
1687 } else {
1688 if (isupper(*s)) return(True);
1689 s++;
1691 #else /* KANJI */
1692 if (isupper(*s)) return(True);
1693 s++;
1694 #endif /* KANJI */
1696 return(False);
1699 /****************************************************************************
1700 does a string have any lowercase chars in it?
1701 ****************************************************************************/
1702 BOOL strhaslower(char *s)
1704 while (*s)
1706 #ifdef KANJI
1707 if (is_shift_jis (*s)) {
1708 if (is_sj_upper (s[0], s[1])) return(True);
1709 if (is_sj_lower (s[0], s[1])) return (True);
1710 s += 2;
1711 } else if (is_kana (*s)) {
1712 s++;
1713 } else {
1714 if (islower(*s)) return(True);
1715 s++;
1717 #else /* KANJI */
1718 if (islower(*s)) return(True);
1719 s++;
1720 #endif /* KANJI */
1722 return(False);
1725 /****************************************************************************
1726 find the number of chars in a string
1727 ****************************************************************************/
1728 int count_chars(char *s,char c)
1730 int count=0;
1731 #ifdef KANJI
1732 while (*s)
1734 if (is_shift_jis (*s))
1735 s += 2;
1736 else
1738 if (*s == c)
1739 count++;
1740 s++;
1743 #else /* KANJI */
1744 while (*s)
1746 if (*s == c)
1747 count++;
1748 s++;
1750 #endif /* KANJI */
1751 return(count);
1755 /****************************************************************************
1756 make a dir struct
1757 ****************************************************************************/
1758 void make_dir_struct(char *buf,char *mask,char *fname,unsigned int size,int mode,time_t date)
1760 char *p;
1761 pstring mask2;
1763 strcpy(mask2,mask);
1765 if ((mode & aDIR) != 0)
1766 size = 0;
1768 memset(buf+1,' ',11);
1769 if ((p = strchr(mask2,'.')) != NULL)
1771 *p = 0;
1772 memcpy(buf+1,mask2,MIN(strlen(mask2),8));
1773 memcpy(buf+9,p+1,MIN(strlen(p+1),3));
1774 *p = '.';
1776 else
1777 memcpy(buf+1,mask2,MIN(strlen(mask2),11));
1779 bzero(buf+21,DIR_STRUCT_SIZE-21);
1780 CVAL(buf,21) = mode;
1781 put_dos_date(buf,22,date);
1782 SSVAL(buf,26,size & 0xFFFF);
1783 SSVAL(buf,28,size >> 16);
1784 StrnCpy(buf+30,fname,12);
1785 if (!case_sensitive)
1786 strupper(buf+30);
1787 DEBUG(8,("put name [%s] into dir struct\n",buf+30));
1791 /*******************************************************************
1792 close the low 3 fd's and open dev/null in their place
1793 ********************************************************************/
1794 void close_low_fds(void)
1796 int fd;
1797 int i;
1798 close(0); close(1); close(2);
1799 /* try and use up these file descriptors, so silly
1800 library routines writing to stdout etc won't cause havoc */
1801 for (i=0;i<3;i++) {
1802 fd = open("/dev/null",O_RDWR,0);
1803 if (fd < 0) fd = open("/dev/null",O_WRONLY,0);
1804 if (fd < 0) {
1805 DEBUG(0,("Can't open /dev/null\n"));
1806 return;
1808 if (fd != i) {
1809 DEBUG(0,("Didn't get file descriptor %d\n",i));
1810 return;
1815 /****************************************************************************
1816 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
1817 else
1818 if SYSV use O_NDELAY
1819 if BSD use FNDELAY
1820 ****************************************************************************/
1821 int set_blocking(int fd, BOOL set)
1823 int val;
1824 #ifdef O_NONBLOCK
1825 #define FLAG_TO_SET O_NONBLOCK
1826 #else
1827 #ifdef SYSV
1828 #define FLAG_TO_SET O_NDELAY
1829 #else /* BSD */
1830 #define FLAG_TO_SET FNDELAY
1831 #endif
1832 #endif
1834 if((val = fcntl(fd, F_GETFL, 0)) == -1)
1835 return -1;
1836 if(set) /* Turn blocking on - ie. clear nonblock flag */
1837 val &= ~FLAG_TO_SET;
1838 else
1839 val |= FLAG_TO_SET;
1840 return fcntl( fd, F_SETFL, val);
1841 #undef FLAG_TO_SET
1845 /****************************************************************************
1846 write to a socket
1847 ****************************************************************************/
1848 int write_socket(int fd,char *buf,int len)
1850 int ret=0;
1852 if (passive)
1853 return(len);
1854 DEBUG(6,("write_socket(%d,%d)\n",fd,len));
1855 ret = write_data(fd,buf,len);
1857 DEBUG(6,("write_socket(%d,%d) wrote %d\n",fd,len,ret));
1858 return(ret);
1861 /****************************************************************************
1862 read from a socket
1863 ****************************************************************************/
1864 int read_udp_socket(int fd,char *buf,int len)
1866 int ret;
1867 struct sockaddr sock;
1868 int socklen;
1870 socklen = sizeof(sock);
1871 bzero((char *)&sock,socklen);
1872 bzero((char *)&lastip,sizeof(lastip));
1873 ret = recvfrom(fd,buf,len,0,&sock,&socklen);
1874 if (ret <= 0) {
1875 DEBUG(2,("read socket failed. ERRNO=%d\n",errno));
1876 return(0);
1879 lastip = *(struct in_addr *) &sock.sa_data[2];
1880 lastport = ntohs(((struct sockaddr_in *)&sock)->sin_port);
1882 return(ret);
1885 /****************************************************************************
1886 read data from a device with a timout in msec.
1887 mincount = if timeout, minimum to read before returning
1888 maxcount = number to be read.
1889 ****************************************************************************/
1890 int read_with_timeout(int fd,char *buf,int mincnt,int maxcnt,long time_out)
1892 fd_set fds;
1893 int selrtn;
1894 int readret;
1895 int nread = 0;
1896 struct timeval timeout;
1898 /* just checking .... */
1899 if (maxcnt <= 0) return(0);
1901 smb_read_error = 0;
1903 /* Blocking read */
1904 if (time_out <= 0) {
1905 if (mincnt == 0) mincnt = maxcnt;
1907 while (nread < mincnt) {
1908 readret = read(fd, buf + nread, maxcnt - nread);
1909 if (readret == 0) {
1910 smb_read_error = READ_EOF;
1911 return -1;
1914 if (readret == -1) {
1915 smb_read_error = READ_ERROR;
1916 return -1;
1918 nread += readret;
1920 return(nread);
1923 /* Most difficult - timeout read */
1924 /* If this is ever called on a disk file and
1925 mincnt is greater then the filesize then
1926 system performance will suffer severely as
1927 select always return true on disk files */
1929 /* Set initial timeout */
1930 timeout.tv_sec = time_out / 1000;
1931 timeout.tv_usec = 1000 * (time_out % 1000);
1933 for (nread=0; nread<mincnt; )
1935 FD_ZERO(&fds);
1936 FD_SET(fd,&fds);
1938 selrtn = sys_select(&fds,&timeout);
1940 /* Check if error */
1941 if(selrtn == -1) {
1942 /* something is wrong. Maybe the socket is dead? */
1943 smb_read_error = READ_ERROR;
1944 return -1;
1947 /* Did we timeout ? */
1948 if (selrtn == 0) {
1949 smb_read_error = READ_TIMEOUT;
1950 return -1;
1953 readret = read(fd, buf+nread, maxcnt-nread);
1954 if (readret == 0) {
1955 /* we got EOF on the file descriptor */
1956 smb_read_error = READ_EOF;
1957 return -1;
1960 if (readret == -1) {
1961 /* the descriptor is probably dead */
1962 smb_read_error = READ_ERROR;
1963 return -1;
1966 nread += readret;
1969 /* Return the number we got */
1970 return(nread);
1973 /****************************************************************************
1974 read data from the client. Maxtime is in milliseconds
1975 ****************************************************************************/
1976 int read_max_udp(int fd,char *buffer,int bufsize,int maxtime)
1978 fd_set fds;
1979 int selrtn;
1980 int nread;
1981 struct timeval timeout;
1983 FD_ZERO(&fds);
1984 FD_SET(fd,&fds);
1986 timeout.tv_sec = maxtime / 1000;
1987 timeout.tv_usec = (maxtime % 1000) * 1000;
1989 selrtn = sys_select(&fds,maxtime>0?&timeout:NULL);
1991 if (!FD_ISSET(fd,&fds))
1992 return 0;
1994 nread = read_udp_socket(fd, buffer, bufsize);
1996 /* return the number got */
1997 return(nread);
2000 /*******************************************************************
2001 find the difference in milliseconds between two struct timeval
2002 values
2003 ********************************************************************/
2004 int TvalDiff(struct timeval *tvalold,struct timeval *tvalnew)
2006 return((tvalnew->tv_sec - tvalold->tv_sec)*1000 +
2007 ((int)tvalnew->tv_usec - (int)tvalold->tv_usec)/1000);
2010 /****************************************************************************
2011 send a keepalive packet (rfc1002)
2012 ****************************************************************************/
2013 BOOL send_keepalive(int client)
2015 unsigned char buf[4];
2017 buf[0] = 0x85;
2018 buf[1] = buf[2] = buf[3] = 0;
2020 return(write_data(client,(char *)buf,4) == 4);
2025 /****************************************************************************
2026 read data from the client, reading exactly N bytes.
2027 ****************************************************************************/
2028 int read_data(int fd,char *buffer,int N)
2030 int ret;
2031 int total=0;
2033 smb_read_error = 0;
2035 while (total < N)
2037 ret = read(fd,buffer + total,N - total);
2038 if (ret == 0) {
2039 smb_read_error = READ_EOF;
2040 return 0;
2042 if (ret == -1) {
2043 smb_read_error = READ_ERROR;
2044 return -1;
2046 total += ret;
2048 return total;
2052 /****************************************************************************
2053 write data to a fd
2054 ****************************************************************************/
2055 int write_data(int fd,char *buffer,int N)
2057 int total=0;
2058 int ret;
2060 while (total < N)
2062 ret = write(fd,buffer + total,N - total);
2064 if (ret == -1) return -1;
2065 if (ret == 0) return total;
2067 total += ret;
2069 return total;
2073 /****************************************************************************
2074 transfer some data between two fd's
2075 ****************************************************************************/
2076 int transfer_file(int infd,int outfd,int n,char *header,int headlen,int align)
2078 static char *buf=NULL;
2079 static int size=0;
2080 char *buf1,*abuf;
2081 int total = 0;
2083 DEBUG(4,("transfer_file %d (head=%d) called\n",n,headlen));
2085 if (size == 0) {
2086 size = lp_readsize();
2087 size = MAX(size,1024);
2090 while (!buf && size>0) {
2091 buf = (char *)Realloc(buf,size+8);
2092 if (!buf) size /= 2;
2095 if (!buf) {
2096 DEBUG(0,("Can't allocate transfer buffer!\n"));
2097 exit(1);
2100 abuf = buf + (align%8);
2102 if (header)
2103 n += headlen;
2105 while (n > 0)
2107 int s = MIN(n,size);
2108 int ret,ret2=0;
2110 ret = 0;
2112 if (header && (headlen >= MIN(s,1024))) {
2113 buf1 = header;
2114 s = headlen;
2115 ret = headlen;
2116 headlen = 0;
2117 header = NULL;
2118 } else {
2119 buf1 = abuf;
2122 if (header && headlen > 0)
2124 ret = MIN(headlen,size);
2125 memcpy(buf1,header,ret);
2126 headlen -= ret;
2127 header += ret;
2128 if (headlen <= 0) header = NULL;
2131 if (s > ret)
2132 ret += read(infd,buf1+ret,s-ret);
2134 if (ret > 0)
2136 ret2 = (outfd>=0?write_data(outfd,buf1,ret):ret);
2137 if (ret2 > 0) total += ret2;
2138 /* if we can't write then dump excess data */
2139 if (ret2 != ret)
2140 transfer_file(infd,-1,n-(ret+headlen),NULL,0,0);
2142 if (ret <= 0 || ret2 != ret)
2143 return(total);
2144 n -= ret;
2146 return(total);
2150 /****************************************************************************
2151 read 4 bytes of a smb packet and return the smb length of the packet
2152 possibly store the result in the buffer
2153 ****************************************************************************/
2154 int read_smb_length(int fd,char *inbuf,int timeout)
2156 char *buffer;
2157 char buf[4];
2158 int len=0, msg_type;
2159 BOOL ok=False;
2161 if (inbuf)
2162 buffer = inbuf;
2163 else
2164 buffer = buf;
2166 while (!ok)
2168 if (timeout > 0)
2169 ok = (read_with_timeout(fd,buffer,4,4,timeout) == 4);
2170 else
2171 ok = (read_data(fd,buffer,4) == 4);
2173 if (!ok)
2174 return(-1);
2176 len = smb_len(buffer);
2177 msg_type = CVAL(buffer,0);
2179 if (msg_type == 0x85)
2181 DEBUG(5,("Got keepalive packet\n"));
2182 ok = False;
2186 DEBUG(10,("got smb length of %d\n",len));
2188 return(len);
2193 /****************************************************************************
2194 read an smb from a fd and return it's length
2195 The timeout is in milli seconds
2196 ****************************************************************************/
2197 BOOL receive_smb(int fd,char *buffer,int timeout)
2199 int len,ret;
2201 smb_read_error = 0;
2203 bzero(buffer,smb_size + 100);
2205 len = read_smb_length(fd,buffer,timeout);
2206 if (len == -1)
2207 return(False);
2209 if (len > BUFFER_SIZE) {
2210 DEBUG(0,("Invalid packet length! (%d bytes).\n",len));
2211 if (len > BUFFER_SIZE + (SAFETY_MARGIN/2))
2212 exit(1);
2215 ret = read_data(fd,buffer+4,len);
2216 if (ret != len) {
2217 smb_read_error = READ_ERROR;
2218 return False;
2221 return(True);
2225 /****************************************************************************
2226 send an smb to a fd
2227 ****************************************************************************/
2228 BOOL send_smb(int fd,char *buffer)
2230 int len;
2231 int ret,nwritten=0;
2232 len = smb_len(buffer) + 4;
2234 while (nwritten < len)
2236 ret = write_socket(fd,buffer+nwritten,len - nwritten);
2237 if (ret <= 0)
2239 DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",len,ret));
2240 close_sockets();
2241 exit(1);
2243 nwritten += ret;
2247 return True;
2251 /****************************************************************************
2252 find a pointer to a netbios name
2253 ****************************************************************************/
2254 char *name_ptr(char *buf,int ofs)
2256 unsigned char c = *(unsigned char *)(buf+ofs);
2258 if ((c & 0xC0) == 0xC0)
2260 uint16 l;
2261 char p[2];
2262 memcpy(p,buf+ofs,2);
2263 p[0] &= ~0xC0;
2264 l = RSVAL(p,0);
2265 DEBUG(5,("name ptr to pos %d from %d is %s\n",l,ofs,buf+l));
2266 return(buf + l);
2268 else
2269 return(buf+ofs);
2272 /****************************************************************************
2273 extract a netbios name from a buf
2274 ****************************************************************************/
2275 int name_extract(char *buf,int ofs,char *name)
2277 char *p = name_ptr(buf,ofs);
2278 int d = PTR_DIFF(p,buf+ofs);
2279 strcpy(name,"");
2280 if (d < -50 || d > 50) return(0);
2281 return(name_interpret(p,name));
2285 /****************************************************************************
2286 return the total storage length of a mangled name
2287 ****************************************************************************/
2288 int name_len(char *s)
2290 char *s0=s;
2291 unsigned char c = *(unsigned char *)s;
2292 if ((c & 0xC0) == 0xC0)
2293 return(2);
2294 while (*s) s += (*s)+1;
2295 return(PTR_DIFF(s,s0)+1);
2298 /****************************************************************************
2299 send a single packet to a port on another machine
2300 ****************************************************************************/
2301 BOOL send_one_packet(char *buf,int len,struct in_addr ip,int port,int type)
2303 BOOL ret;
2304 int out_fd;
2305 struct sockaddr_in sock_out;
2307 if (passive)
2308 return(True);
2310 /* create a socket to write to */
2311 out_fd = socket(AF_INET, type, 0);
2312 if (out_fd == -1)
2314 DEBUG(0,("socket failed"));
2315 return False;
2318 /* set the address and port */
2319 bzero((char *)&sock_out,sizeof(sock_out));
2320 putip((char *)&sock_out.sin_addr,(char *)&ip);
2321 sock_out.sin_port = htons( port );
2322 sock_out.sin_family = AF_INET;
2324 if (DEBUGLEVEL > 0)
2325 DEBUG(3,("sending a packet of len %d to (%s) on port %d of type %s\n",
2326 len,inet_ntoa(ip),port,type==SOCK_DGRAM?"DGRAM":"STREAM"));
2328 /* send it */
2329 ret = (sendto(out_fd,buf,len,0,(struct sockaddr *)&sock_out,sizeof(sock_out)) >= 0);
2331 if (!ret)
2332 DEBUG(0,("Packet send to %s(%d) failed ERRNO=%d\n",
2333 inet_ntoa(ip),port,errno));
2335 close(out_fd);
2336 return(ret);
2339 /*******************************************************************
2340 sleep for a specified number of milliseconds
2341 ********************************************************************/
2342 void msleep(int t)
2344 int tdiff=0;
2345 struct timeval tval,t1,t2;
2346 fd_set fds;
2348 GetTimeOfDay(&t1);
2349 GetTimeOfDay(&t2);
2351 while (tdiff < t) {
2352 tval.tv_sec = (t-tdiff)/1000;
2353 tval.tv_usec = 1000*((t-tdiff)%1000);
2355 FD_ZERO(&fds);
2356 errno = 0;
2357 sys_select(&fds,&tval);
2359 GetTimeOfDay(&t2);
2360 tdiff = TvalDiff(&t1,&t2);
2364 /****************************************************************************
2365 check if a string is part of a list
2366 ****************************************************************************/
2367 BOOL in_list(char *s,char *list,BOOL casesensitive)
2369 pstring tok;
2370 char *p=list;
2372 if (!list) return(False);
2374 while (next_token(&p,tok,LIST_SEP))
2376 if (casesensitive) {
2377 if (strcmp(tok,s) == 0)
2378 return(True);
2379 } else {
2380 if (StrCaseCmp(tok,s) == 0)
2381 return(True);
2384 return(False);
2387 /* this is used to prevent lots of mallocs of size 1 */
2388 static char *null_string = NULL;
2390 /****************************************************************************
2391 set a string value, allocing the space for the string
2392 ****************************************************************************/
2393 BOOL string_init(char **dest,char *src)
2395 int l;
2396 if (!src)
2397 src = "";
2399 l = strlen(src);
2401 if (l == 0)
2403 if (!null_string)
2404 null_string = (char *)malloc(1);
2406 *null_string = 0;
2407 *dest = null_string;
2409 else
2411 *dest = (char *)malloc(l+1);
2412 strcpy(*dest,src);
2414 return(True);
2417 /****************************************************************************
2418 free a string value
2419 ****************************************************************************/
2420 void string_free(char **s)
2422 if (!s || !(*s)) return;
2423 if (*s == null_string)
2424 *s = NULL;
2425 if (*s) free(*s);
2426 *s = NULL;
2429 /****************************************************************************
2430 set a string value, allocing the space for the string, and deallocating any
2431 existing space
2432 ****************************************************************************/
2433 BOOL string_set(char **dest,char *src)
2435 string_free(dest);
2437 return(string_init(dest,src));
2440 /****************************************************************************
2441 substitute a string for a pattern in another string. Make sure there is
2442 enough room!
2444 This routine looks for pattern in s and replaces it with
2445 insert. It may do multiple replacements.
2447 return True if a substitution was done.
2448 ****************************************************************************/
2449 BOOL string_sub(char *s,char *pattern,char *insert)
2451 BOOL ret = False;
2452 char *p;
2453 int ls,lp,li;
2455 if (!insert || !pattern || !s) return(False);
2457 ls = strlen(s);
2458 lp = strlen(pattern);
2459 li = strlen(insert);
2461 if (!*pattern) return(False);
2463 while (lp <= ls && (p = strstr(s,pattern)))
2465 ret = True;
2466 memmove(p+li,p+lp,ls + 1 - (PTR_DIFF(p,s) + lp));
2467 memcpy(p,insert,li);
2468 s = p + li;
2469 ls = strlen(s);
2471 return(ret);
2476 /*********************************************************
2477 * Recursive routine that is called by mask_match.
2478 * Does the actual matching.
2479 *********************************************************/
2480 BOOL do_match(char *str, char *regexp, int case_sig)
2482 char *p;
2484 for( p = regexp; *p && *str; ) {
2485 switch(*p) {
2486 case '?':
2487 str++; p++;
2488 break;
2490 case '*':
2491 /* Look for a character matching
2492 the one after the '*' */
2493 p++;
2494 if(!*p)
2495 return True; /* Automatic match */
2496 while(*str) {
2497 while(*str && (case_sig ? (*p != *str) : (toupper(*p)!=toupper(*str))))
2498 str++;
2499 if(do_match(str,p,case_sig))
2500 return True;
2501 if(!*str)
2502 return False;
2503 else
2504 str++;
2506 return False;
2508 default:
2509 if(case_sig) {
2510 if(*str != *p)
2511 return False;
2512 } else {
2513 if(toupper(*str) != toupper(*p))
2514 return False;
2516 str++, p++;
2517 break;
2520 if(!*p && !*str)
2521 return True;
2523 if (!*p && str[0] == '.' && str[1] == 0)
2524 return(True);
2526 if (!*str && *p == '?')
2528 while (*p == '?') p++;
2529 return(!*p);
2532 if(!*str && (*p == '*' && p[1] == '\0'))
2533 return True;
2534 return False;
2538 /*********************************************************
2539 * Routine to match a given string with a regexp - uses
2540 * simplified regexp that takes * and ? only. Case can be
2541 * significant or not.
2542 *********************************************************/
2543 BOOL mask_match(char *str, char *regexp, int case_sig,BOOL trans2)
2545 char *p;
2546 pstring p1, p2;
2547 fstring ebase,eext,sbase,sext;
2549 BOOL matched;
2551 /* Make local copies of str and regexp */
2552 StrnCpy(p1,regexp,sizeof(pstring)-1);
2553 StrnCpy(p2,str,sizeof(pstring)-1);
2555 if (!strchr(p2,'.')) {
2556 strcat(p2,".");
2560 if (!strchr(p1,'.')) {
2561 strcat(p1,".");
2565 #if 0
2566 if (strchr(p1,'.'))
2568 string_sub(p1,"*.*","*");
2569 string_sub(p1,".*","*");
2571 #endif
2573 /* Remove any *? and ** as they are meaningless */
2574 for(p = p1; *p; p++)
2575 while( *p == '*' && (p[1] == '?' ||p[1] == '*'))
2576 (void)strcpy( &p[1], &p[2]);
2578 if (strequal(p1,"*")) return(True);
2580 DEBUG(5,("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
2582 if (trans2) {
2583 strcpy(ebase,p1);
2584 strcpy(sbase,p2);
2585 } else {
2586 if ((p=strrchr(p1,'.'))) {
2587 *p = 0;
2588 strcpy(ebase,p1);
2589 strcpy(eext,p+1);
2590 } else {
2591 strcpy(ebase,p1);
2592 eext[0] = 0;
2595 if (!strequal(p2,".") && !strequal(p2,"..") && (p=strrchr(p2,'.'))) {
2596 *p = 0;
2597 strcpy(sbase,p2);
2598 strcpy(sext,p+1);
2599 } else {
2600 strcpy(sbase,p2);
2601 strcpy(sext,"");
2605 matched = do_match(sbase,ebase,case_sig) &&
2606 (trans2 || do_match(sext,eext,case_sig));
2608 DEBUG(5,("mask_match returning %d\n", matched));
2610 return matched;
2615 /****************************************************************************
2616 become a daemon, discarding the controlling terminal
2617 ****************************************************************************/
2618 void become_daemon(void)
2620 #ifndef NO_FORK_DEBUG
2621 if (fork())
2622 exit(0);
2624 /* detach from the terminal */
2625 #ifdef USE_SETSID
2626 setsid();
2627 #else /* USE_SETSID */
2628 #ifdef TIOCNOTTY
2630 int i = open("/dev/tty", O_RDWR);
2631 if (i >= 0)
2633 ioctl(i, (int) TIOCNOTTY, (char *)0);
2634 close(i);
2637 #endif /* TIOCNOTTY */
2638 #endif /* USE_SETSID */
2639 /* Close fd's 0,1,2. Needed if started by rsh */
2640 close_low_fds();
2641 #endif /* NO_FORK_DEBUG */
2645 /****************************************************************************
2646 put up a yes/no prompt
2647 ****************************************************************************/
2648 BOOL yesno(char *p)
2650 pstring ans;
2651 printf("%s",p);
2653 if (!fgets(ans,sizeof(ans)-1,stdin))
2654 return(False);
2656 if (*ans == 'y' || *ans == 'Y')
2657 return(True);
2659 return(False);
2662 /****************************************************************************
2663 read a line from a file with possible \ continuation chars.
2664 Blanks at the start or end of a line are stripped.
2665 The string will be allocated if s2 is NULL
2666 ****************************************************************************/
2667 char *fgets_slash(char *s2,int maxlen,FILE *f)
2669 char *s=s2;
2670 int len = 0;
2671 int c;
2672 BOOL start_of_line = True;
2674 if (feof(f))
2675 return(NULL);
2677 if (!s2)
2679 maxlen = MIN(maxlen,8);
2680 s = (char *)Realloc(s,maxlen);
2683 if (!s || maxlen < 2) return(NULL);
2685 *s = 0;
2687 while (len < maxlen-1)
2689 c = getc(f);
2690 switch (c)
2692 case '\r':
2693 break;
2694 case '\n':
2695 while (len > 0 && s[len-1] == ' ')
2697 s[--len] = 0;
2699 if (len > 0 && s[len-1] == '\\')
2701 s[--len] = 0;
2702 start_of_line = True;
2703 break;
2705 return(s);
2706 case EOF:
2707 if (len <= 0 && !s2)
2708 free(s);
2709 return(len>0?s:NULL);
2710 case ' ':
2711 if (start_of_line)
2712 break;
2713 default:
2714 start_of_line = False;
2715 s[len++] = c;
2716 s[len] = 0;
2718 if (!s2 && len > maxlen-3)
2720 maxlen *= 2;
2721 s = (char *)Realloc(s,maxlen);
2722 if (!s) return(NULL);
2725 return(s);
2730 /****************************************************************************
2731 set the length of a file from a filedescriptor.
2732 Returns 0 on success, -1 on failure.
2733 ****************************************************************************/
2734 int set_filelen(int fd, long len)
2736 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
2737 extend a file with ftruncate. Provide alternate implementation
2738 for this */
2740 #if FTRUNCATE_CAN_EXTEND
2741 return ftruncate(fd, len);
2742 #else
2743 struct stat st;
2744 char c = 0;
2745 long currpos = lseek(fd, 0L, SEEK_CUR);
2747 if(currpos < 0)
2748 return -1;
2749 /* Do an fstat to see if the file is longer than
2750 the requested size (call ftruncate),
2751 or shorter, in which case seek to len - 1 and write 1
2752 byte of zero */
2753 if(fstat(fd, &st)<0)
2754 return -1;
2756 #ifdef S_ISFIFO
2757 if (S_ISFIFO(st.st_mode)) return 0;
2758 #endif
2760 if(st.st_size == len)
2761 return 0;
2762 if(st.st_size > len)
2763 return ftruncate(fd, len);
2765 if(lseek(fd, len-1, SEEK_SET) != len -1)
2766 return -1;
2767 if(write(fd, &c, 1)!=1)
2768 return -1;
2769 /* Seek to where we were */
2770 lseek(fd, currpos, SEEK_SET);
2771 return 0;
2772 #endif
2776 /****************************************************************************
2777 return the byte checksum of some data
2778 ****************************************************************************/
2779 int byte_checksum(char *buf,int len)
2781 unsigned char *p = (unsigned char *)buf;
2782 int ret = 0;
2783 while (len--)
2784 ret += *p++;
2785 return(ret);
2790 #ifdef HPUX
2791 /****************************************************************************
2792 this is a version of setbuffer() for those machines that only have setvbuf
2793 ****************************************************************************/
2794 void setbuffer(FILE *f,char *buf,int bufsize)
2796 setvbuf(f,buf,_IOFBF,bufsize);
2798 #endif
2801 /****************************************************************************
2802 parse out a directory name from a path name. Assumes dos style filenames.
2803 ****************************************************************************/
2804 char *dirname_dos(char *path,char *buf)
2806 char *p = strrchr(path,'\\');
2808 if (!p)
2809 strcpy(buf,path);
2810 else
2812 *p = 0;
2813 strcpy(buf,path);
2814 *p = '\\';
2817 return(buf);
2821 /****************************************************************************
2822 parse out a filename from a path name. Assumes dos style filenames.
2823 ****************************************************************************/
2824 static char *filename_dos(char *path,char *buf)
2826 char *p = strrchr(path,'\\');
2828 if (!p)
2829 strcpy(buf,path);
2830 else
2831 strcpy(buf,p+1);
2833 return(buf);
2838 /****************************************************************************
2839 expand a pointer to be a particular size
2840 ****************************************************************************/
2841 void *Realloc(void *p,int size)
2843 void *ret=NULL;
2845 if (size == 0) {
2846 if (p) free(p);
2847 DEBUG(5,("Realloc asked for 0 bytes\n"));
2848 return NULL;
2851 if (!p)
2852 ret = (void *)malloc(size);
2853 else
2854 ret = (void *)realloc(p,size);
2856 if (!ret)
2857 DEBUG(0,("Memory allocation error: failed to expand to %d bytes\n",size));
2859 return(ret);
2862 #ifdef NOSTRDUP
2863 /****************************************************************************
2864 duplicate a string
2865 ****************************************************************************/
2866 char *strdup(char *s)
2868 char *ret = NULL;
2869 if (!s) return(NULL);
2870 ret = (char *)malloc(strlen(s)+1);
2871 if (!ret) return(NULL);
2872 strcpy(ret,s);
2873 return(ret);
2875 #endif
2878 /****************************************************************************
2879 Signal handler for SIGPIPE (write on a disconnected socket)
2880 ****************************************************************************/
2881 void Abort(void )
2883 DEBUG(0,("Probably got SIGPIPE\nExiting\n"));
2884 exit(2);
2887 /****************************************************************************
2888 get my own name and IP
2889 ****************************************************************************/
2890 BOOL get_myname(char *my_name,struct in_addr *ip)
2892 struct hostent *hp;
2893 pstring hostname;
2895 *hostname = 0;
2897 /* get my host name */
2898 if (gethostname(hostname, MAXHOSTNAMELEN) == -1)
2900 DEBUG(0,("gethostname failed\n"));
2901 return False;
2904 /* get host info */
2905 if ((hp = Get_Hostbyname(hostname)) == 0)
2907 DEBUG(0,( "Get_Hostbyname: Unknown host %s.\n",hostname));
2908 return False;
2911 if (my_name)
2913 /* split off any parts after an initial . */
2914 char *p = strchr(hostname,'.');
2915 if (p) *p = 0;
2917 strcpy(my_name,hostname);
2920 if (ip)
2921 putip((char *)ip,(char *)hp->h_addr);
2923 return(True);
2927 /****************************************************************************
2928 true if two IP addresses are equal
2929 ****************************************************************************/
2930 BOOL ip_equal(struct in_addr ip1,struct in_addr ip2)
2932 uint32 a1,a2;
2933 a1 = ntohl(ip1.s_addr);
2934 a2 = ntohl(ip2.s_addr);
2935 return(a1 == a2);
2939 /****************************************************************************
2940 open a socket of the specified type, port and address for incoming data
2941 ****************************************************************************/
2942 int open_socket_in(int type, int port, int dlevel,uint32 socket_addr)
2944 struct hostent *hp;
2945 struct sockaddr_in sock;
2946 pstring host_name;
2947 int res;
2949 /* get my host name */
2950 if (gethostname(host_name, MAXHOSTNAMELEN) == -1)
2951 { DEBUG(0,("gethostname failed\n")); return -1; }
2953 /* get host info */
2954 if ((hp = Get_Hostbyname(host_name)) == 0)
2956 DEBUG(0,( "Get_Hostbyname: Unknown host. %s\n",host_name));
2957 return -1;
2960 bzero((char *)&sock,sizeof(sock));
2961 memcpy((char *)&sock.sin_addr,(char *)hp->h_addr, hp->h_length);
2962 #if defined(__FreeBSD__) || defined(NETBSD) /* XXX not the right ifdef */
2963 sock.sin_len = sizeof(sock);
2964 #endif
2965 sock.sin_port = htons( port );
2966 sock.sin_family = hp->h_addrtype;
2967 sock.sin_addr.s_addr = socket_addr;
2968 res = socket(hp->h_addrtype, type, 0);
2969 if (res == -1)
2970 { DEBUG(0,("socket failed\n")); return -1; }
2973 int one=1;
2974 setsockopt(res,SOL_SOCKET,SO_REUSEADDR,(char *)&one,sizeof(one));
2977 /* now we've got a socket - we need to bind it */
2978 if (bind(res, (struct sockaddr * ) &sock,sizeof(sock)) < 0)
2980 if (port) {
2981 if (port == SMB_PORT || port == NMB_PORT)
2982 DEBUG(dlevel,("bind failed on port %d socket_addr=%x (%s)\n",
2983 port,socket_addr,strerror(errno)));
2984 close(res);
2986 if (dlevel > 0 && port < 1000)
2987 port = 7999;
2989 if (port >= 1000 && port < 9000)
2990 return(open_socket_in(type,port+1,dlevel,socket_addr));
2993 return(-1);
2995 DEBUG(3,("bind succeeded on port %d\n",port));
2997 return res;
3001 /****************************************************************************
3002 create an outgoing socket
3003 **************************************************************************/
3004 int open_socket_out(int type, struct in_addr *addr, int port ,int timeout)
3006 struct sockaddr_in sock_out;
3007 int res,ret;
3008 int connect_loop = 250; /* 250 milliseconds */
3009 int loops = (timeout * 1000) / connect_loop;
3011 /* create a socket to write to */
3012 res = socket(PF_INET, type, 0);
3013 if (res == -1)
3014 { DEBUG(0,("socket error\n")); return -1; }
3016 if (type != SOCK_STREAM) return(res);
3018 bzero((char *)&sock_out,sizeof(sock_out));
3019 putip((char *)&sock_out.sin_addr,(char *)addr);
3021 sock_out.sin_port = htons( port );
3022 sock_out.sin_family = PF_INET;
3024 /* set it non-blocking */
3025 set_blocking(res,False);
3027 DEBUG(3,("Connecting to %s at port %d\n",inet_ntoa(*addr),port));
3029 /* and connect it to the destination */
3030 connect_again:
3031 ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out));
3033 /* Some systems return EAGAIN when they mean EINPROGRESS */
3034 if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3035 errno == EAGAIN) && loops--) {
3036 msleep(connect_loop);
3037 goto connect_again;
3040 if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY ||
3041 errno == EAGAIN)) {
3042 DEBUG(1,("timeout connecting to %s:%d\n",inet_ntoa(*addr),port));
3043 close(res);
3044 return -1;
3047 #ifdef EISCONN
3048 if (ret < 0 && errno == EISCONN) {
3049 errno = 0;
3050 ret = 0;
3052 #endif
3054 if (ret < 0) {
3055 DEBUG(1,("error connecting to %s:%d (%s)\n",
3056 inet_ntoa(*addr),port,strerror(errno)));
3057 return -1;
3060 /* set it blocking again */
3061 set_blocking(res,True);
3063 return res;
3067 /****************************************************************************
3068 interpret a protocol description string, with a default
3069 ****************************************************************************/
3070 int interpret_protocol(char *str,int def)
3072 if (strequal(str,"NT1"))
3073 return(PROTOCOL_NT1);
3074 if (strequal(str,"LANMAN2"))
3075 return(PROTOCOL_LANMAN2);
3076 if (strequal(str,"LANMAN1"))
3077 return(PROTOCOL_LANMAN1);
3078 if (strequal(str,"CORE"))
3079 return(PROTOCOL_CORE);
3080 if (strequal(str,"COREPLUS"))
3081 return(PROTOCOL_COREPLUS);
3082 if (strequal(str,"CORE+"))
3083 return(PROTOCOL_COREPLUS);
3085 DEBUG(0,("Unrecognised protocol level %s\n",str));
3087 return(def);
3090 /****************************************************************************
3091 interpret a security level
3092 ****************************************************************************/
3093 int interpret_security(char *str,int def)
3095 if (strequal(str,"SERVER"))
3096 return(SEC_SERVER);
3097 if (strequal(str,"USER"))
3098 return(SEC_USER);
3099 if (strequal(str,"SHARE"))
3100 return(SEC_SHARE);
3102 DEBUG(0,("Unrecognised security level %s\n",str));
3104 return(def);
3108 /****************************************************************************
3109 interpret an internet address or name into an IP address in 4 byte form
3110 ****************************************************************************/
3111 uint32 interpret_addr(char *str)
3113 struct hostent *hp;
3114 uint32 res;
3115 int i;
3116 BOOL pure_address = True;
3118 if (strcmp(str,"0.0.0.0") == 0) return(0);
3119 if (strcmp(str,"255.255.255.255") == 0) return(0xFFFFFFFF);
3121 for (i=0; pure_address && str[i]; i++)
3122 if (!(isdigit(str[i]) || str[i] == '.'))
3123 pure_address = False;
3125 /* if it's in the form of an IP address then get the lib to interpret it */
3126 if (pure_address) {
3127 res = inet_addr(str);
3128 } else {
3129 /* otherwise assume it's a network name of some sort and use
3130 Get_Hostbyname */
3131 if ((hp = Get_Hostbyname(str)) == 0) {
3132 DEBUG(3,("Get_Hostbyname: Unknown host. %s\n",str));
3133 return 0;
3135 putip((char *)&res,(char *)hp->h_addr);
3138 if (res == (uint32)-1) return(0);
3140 return(res);
3143 /*******************************************************************
3144 a convenient addition to interpret_addr()
3145 ******************************************************************/
3146 struct in_addr *interpret_addr2(char *str)
3148 static struct in_addr ret;
3149 uint32 a = interpret_addr(str);
3150 ret.s_addr = a;
3151 return(&ret);
3154 /*******************************************************************
3155 check if an IP is the 0.0.0.0
3156 ******************************************************************/
3157 BOOL zero_ip(struct in_addr ip)
3159 uint32 a;
3160 putip((char *)&a,(char *)&ip);
3161 return(a == 0);
3165 /*******************************************************************
3166 matchname - determine if host name matches IP address
3167 ******************************************************************/
3168 static BOOL matchname(char *remotehost,struct in_addr addr)
3170 struct hostent *hp;
3171 int i;
3173 if ((hp = Get_Hostbyname(remotehost)) == 0) {
3174 DEBUG(0,("Get_Hostbyname(%s): lookup failure", remotehost));
3175 return False;
3179 * Make sure that gethostbyname() returns the "correct" host name.
3180 * Unfortunately, gethostbyname("localhost") sometimes yields
3181 * "localhost.domain". Since the latter host name comes from the
3182 * local DNS, we just have to trust it (all bets are off if the local
3183 * DNS is perverted). We always check the address list, though.
3186 if (strcasecmp(remotehost, hp->h_name)
3187 && strcasecmp(remotehost, "localhost")) {
3188 DEBUG(0,("host name/name mismatch: %s != %s",
3189 remotehost, hp->h_name));
3190 return False;
3193 /* Look up the host address in the address list we just got. */
3194 for (i = 0; hp->h_addr_list[i]; i++) {
3195 if (memcmp(hp->h_addr_list[i], (caddr_t) & addr, sizeof(addr)) == 0)
3196 return True;
3200 * The host name does not map to the original host address. Perhaps
3201 * someone has compromised a name server. More likely someone botched
3202 * it, but that could be dangerous, too.
3205 DEBUG(0,("host name/address mismatch: %s != %s",
3206 inet_ntoa(addr), hp->h_name));
3207 return False;
3210 /*******************************************************************
3211 Reset the 'done' variables so after a client process is created
3212 from a fork call these calls will be re-done. This should be
3213 expanded if more variables need reseting.
3214 ******************************************************************/
3216 static BOOL global_client_name_done = False;
3217 static BOOL global_client_addr_done = False;
3219 void reset_globals_after_fork()
3221 global_client_name_done = False;
3222 global_client_addr_done = False;
3225 /*******************************************************************
3226 return the DNS name of the client
3227 ******************************************************************/
3228 char *client_name(void)
3230 extern int Client;
3231 struct sockaddr sa;
3232 struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3233 int length = sizeof(sa);
3234 static pstring name_buf;
3235 struct hostent *hp;
3237 if (global_client_name_done)
3238 return name_buf;
3240 strcpy(name_buf,"UNKNOWN");
3242 if (getpeername(Client, &sa, &length) < 0) {
3243 DEBUG(0,("getpeername failed\n"));
3244 return name_buf;
3247 /* Look up the remote host name. */
3248 if ((hp = gethostbyaddr((char *) &sockin->sin_addr,
3249 sizeof(sockin->sin_addr),
3250 AF_INET)) == 0) {
3251 DEBUG(1,("Gethostbyaddr failed for %s\n",client_addr()));
3252 StrnCpy(name_buf,client_addr(),sizeof(name_buf) - 1);
3253 } else {
3254 StrnCpy(name_buf,(char *)hp->h_name,sizeof(name_buf) - 1);
3255 if (!matchname(name_buf, sockin->sin_addr)) {
3256 DEBUG(0,("Matchname failed on %s %s\n",name_buf,client_addr()));
3257 strcpy(name_buf,"UNKNOWN");
3260 global_client_name_done = True;
3261 return name_buf;
3264 /*******************************************************************
3265 return the IP addr of the client as a string
3266 ******************************************************************/
3267 char *client_addr(void)
3269 extern int Client;
3270 struct sockaddr sa;
3271 struct sockaddr_in *sockin = (struct sockaddr_in *) (&sa);
3272 int length = sizeof(sa);
3273 static fstring addr_buf;
3275 if (global_client_addr_done)
3276 return addr_buf;
3278 strcpy(addr_buf,"0.0.0.0");
3280 if (getpeername(Client, &sa, &length) < 0) {
3281 DEBUG(0,("getpeername failed\n"));
3282 return addr_buf;
3285 strcpy(addr_buf,(char *)inet_ntoa(sockin->sin_addr));
3287 global_client_addr_done = True;
3288 return addr_buf;
3291 /*******************************************************************
3292 sub strings with useful parameters
3293 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
3294 Paul Rippin <pr3245@nopc.eurostat.cec.be>
3295 ********************************************************************/
3296 void standard_sub_basic(char *string)
3298 char *s, *p;
3299 char pidstr[10];
3300 struct passwd *pass;
3302 for (s = string ; (p = strchr(s,'%')) != NULL ; s = p )
3304 switch (*(p+1))
3306 case 'G' : if ((pass = Get_Pwnam(sesssetup_user,False))!=NULL)
3307 string_sub(p,"%G",gidtoname(pass->pw_gid));
3308 else
3309 p += 2;
3310 break;
3311 case 'I' : string_sub(p,"%I",client_addr()); break;
3312 case 'L' : string_sub(p,"%L",local_machine); break;
3313 case 'M' : string_sub(p,"%M",client_name()); break;
3314 case 'R' : string_sub(p,"%R",remote_proto); break;
3315 case 'T' : string_sub(p,"%T",timestring()); break;
3316 case 'U' : string_sub(p,"%U",sesssetup_user); break;
3317 case 'a' : string_sub(p,"%a",remote_arch); break;
3318 case 'd' : sprintf(pidstr,"%d",(int)getpid());
3319 string_sub(p,"%d",pidstr);
3320 break;
3321 case 'h' : string_sub(p,"%h",myhostname); break;
3322 case 'm' : string_sub(p,"%m",remote_machine); break;
3323 case 'v' : string_sub(p,"%v",VERSION); break;
3324 case '\0' : p++; break; /* don't run off end if last character is % */
3325 default : p+=2; break;
3328 return;
3331 /*******************************************************************
3332 are two IPs on the same subnet?
3333 ********************************************************************/
3334 BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask)
3336 uint32 net1,net2,nmask;
3338 nmask = ntohl(mask.s_addr);
3339 net1 = ntohl(ip1.s_addr);
3340 net2 = ntohl(ip2.s_addr);
3342 return((net1 & nmask) == (net2 & nmask));
3346 /*******************************************************************
3347 write a string in unicoode format
3348 ********************************************************************/
3349 int PutUniCode(char *dst,char *src)
3351 int ret = 0;
3352 while (*src) {
3353 dst[ret++] = src[0];
3354 dst[ret++] = 0;
3355 src++;
3357 dst[ret++]=0;
3358 dst[ret++]=0;
3359 return(ret);
3362 /****************************************************************************
3363 a wrapper for gethostbyname() that tries with all lower and all upper case
3364 if the initial name fails
3365 ****************************************************************************/
3366 struct hostent *Get_Hostbyname(char *name)
3368 char *name2 = strdup(name);
3369 struct hostent *ret;
3371 if (!name2)
3373 DEBUG(0,("Memory allocation error in Get_Hostbyname! panic\n"));
3374 exit(0);
3377 if (!isalnum(*name2))
3379 free(name2);
3380 return(NULL);
3383 ret = sys_gethostbyname(name2);
3384 if (ret != NULL)
3386 free(name2);
3387 return(ret);
3390 /* try with all lowercase */
3391 strlower(name2);
3392 ret = sys_gethostbyname(name2);
3393 if (ret != NULL)
3395 free(name2);
3396 return(ret);
3399 /* try with all uppercase */
3400 strupper(name2);
3401 ret = sys_gethostbyname(name2);
3402 if (ret != NULL)
3404 free(name2);
3405 return(ret);
3408 /* nothing works :-( */
3409 free(name2);
3410 return(NULL);
3414 /****************************************************************************
3415 check if a process exists. Does this work on all unixes?
3416 ****************************************************************************/
3417 BOOL process_exists(int pid)
3419 #ifdef LINUX
3420 fstring s;
3421 sprintf(s,"/proc/%d",pid);
3422 return(directory_exist(s,NULL));
3423 #else
3425 static BOOL tested=False;
3426 static BOOL ok=False;
3427 fstring s;
3428 if (!tested) {
3429 tested = True;
3430 sprintf(s,"/proc/%05d",(int)getpid());
3431 ok = file_exist(s,NULL);
3433 if (ok) {
3434 sprintf(s,"/proc/%05d",pid);
3435 return(file_exist(s,NULL));
3439 /* CGH 8/16/96 - added ESRCH test */
3440 return(pid == getpid() || kill(pid,0) == 0 || errno != ESRCH);
3441 #endif
3445 /*******************************************************************
3446 turn a uid into a user name
3447 ********************************************************************/
3448 char *uidtoname(int uid)
3450 static char name[40];
3451 struct passwd *pass = getpwuid(uid);
3452 if (pass) return(pass->pw_name);
3453 sprintf(name,"%d",uid);
3454 return(name);
3457 /*******************************************************************
3458 turn a gid into a group name
3459 ********************************************************************/
3460 char *gidtoname(int gid)
3462 static char name[40];
3463 struct group *grp = getgrgid(gid);
3464 if (grp) return(grp->gr_name);
3465 sprintf(name,"%d",gid);
3466 return(name);
3469 /*******************************************************************
3470 block sigs
3471 ********************************************************************/
3472 void BlockSignals(BOOL block,int signum)
3474 #ifdef USE_SIGBLOCK
3475 int block_mask = sigmask(signum);
3476 static int oldmask = 0;
3477 if (block)
3478 oldmask = sigblock(block_mask);
3479 else
3480 sigsetmask(oldmask);
3481 #elif defined(USE_SIGPROCMASK)
3482 sigset_t set;
3483 sigemptyset(&set);
3484 sigaddset(&set,signum);
3485 sigprocmask(block?SIG_BLOCK:SIG_UNBLOCK,&set,NULL);
3486 #endif
3489 #if AJT
3490 /*******************************************************************
3491 my own panic function - not suitable for general use
3492 ********************************************************************/
3493 void ajt_panic(void)
3495 system("/usr/bin/X11/xedit -display ljus:0 /tmp/ERROR_FAULT");
3497 #endif
3499 #ifdef USE_DIRECT
3500 #define DIRECT direct
3501 #else
3502 #define DIRECT dirent
3503 #endif
3505 /*******************************************************************
3506 a readdir wrapper which just returns the file name
3507 also return the inode number if requested
3508 ********************************************************************/
3509 char *readdirname(void *p)
3511 struct DIRECT *ptr;
3512 char *dname;
3514 if (!p) return(NULL);
3516 ptr = (struct DIRECT *)readdir(p);
3517 if (!ptr) return(NULL);
3519 dname = ptr->d_name;
3521 #ifdef NEXT2
3522 if (telldir(p) < 0) return(NULL);
3523 #endif
3525 #ifdef SUNOS5
3526 /* this handles a broken compiler setup, causing a mixture
3527 of BSD and SYSV headers and libraries */
3529 static BOOL broken_readdir = False;
3530 if (!broken_readdir && !(*(dname)) && strequal("..",dname-2))
3532 DEBUG(0,("Your readdir() is broken. You have somehow mixed SYSV and BSD headers and libraries\n"));
3533 broken_readdir = True;
3535 if (broken_readdir)
3536 dname = dname - 2;
3538 #endif
3541 static pstring buf;
3542 strcpy(buf, dname);
3543 unix_to_dos(buf, True);
3544 dname = buf;
3547 return(dname);
3551 * Utility function used to decide if the last component
3552 * of a path matches a (possibly wildcarded) entry in a namelist.
3555 BOOL is_in_path(char *name, name_compare_entry *namelist)
3557 pstring last_component;
3558 char *p;
3560 DEBUG(5, ("is_in_path: %s\n", name));
3562 /* if we have no list it's obviously not in the path */
3563 if((namelist == NULL ) || ((namelist != NULL) && (namelist[0].name == NULL)))
3565 DEBUG(5,("is_in_path: no name list.\n"));
3566 return False;
3569 /* Get the last component of the unix name. */
3570 p = strrchr(name, '/');
3571 strncpy(last_component, p ? p : name, sizeof(last_component)-1);
3572 last_component[sizeof(last_component)-1] = '\0';
3574 for(; namelist->name != NULL; namelist++)
3576 if(namelist->is_wild)
3578 /* look for a wildcard match. */
3579 if (mask_match(last_component, namelist->name, case_sensitive, False))
3581 DEBUG(5,("is_in_path: mask match succeeded\n"));
3582 return True;
3585 else
3587 if((case_sensitive && (strcmp(last_component, namelist->name) == 0))||
3588 (!case_sensitive && (StrCaseCmp(last_component, namelist->name) == 0)))
3590 DEBUG(5,("is_in_path: match succeeded\n"));
3591 return True;
3595 DEBUG(5,("is_in_path: match not found\n"));
3597 return False;
3601 * Strip a '/' separated list into an array of
3602 * name_compare_enties structures suitable for
3603 * passing to is_in_path(). We do this for
3604 * speed so we can pre-parse all the names in the list
3605 * and don't do it for each call to is_in_path().
3606 * namelist is modified here and is assumed to be
3607 * a copy owned by the caller.
3608 * We also check if the entry contains a wildcard to
3609 * remove a potentially expensive call to mask_match
3610 * if possible.
3613 void set_namearray(name_compare_entry **ppname_array, char *namelist)
3615 char *name_end;
3616 char *nameptr = namelist;
3617 int num_entries = 0;
3618 int i;
3620 (*ppname_array) = NULL;
3622 if((nameptr == NULL ) || ((nameptr != NULL) && (*nameptr == '\0')))
3623 return;
3625 /* We need to make two passes over the string. The
3626 first to count the number of elements, the second
3627 to split it.
3629 while (*nameptr )
3631 if ( *nameptr == '/' )
3633 /* cope with multiple (useless) /s) */
3634 nameptr++;
3635 continue;
3637 /* find the next / */
3638 name_end = strchr(nameptr, '/');
3640 /* oops - the last check for a / didn't find one. */
3641 if (name_end == NULL)
3642 break;
3644 /* next segment please */
3645 nameptr = name_end + 1;
3646 num_entries++;
3649 if(num_entries == 0)
3650 return;
3652 if(( (*ppname_array) = (name_compare_entry *)malloc(
3653 (num_entries + 1) * sizeof(name_compare_entry))) == NULL)
3655 DEBUG(0,("set_namearray: malloc fail\n"));
3656 return;
3659 /* Now copy out the names */
3660 nameptr = namelist;
3661 i = 0;
3662 while(*nameptr)
3664 if ( *nameptr == '/' )
3666 /* cope with multiple (useless) /s) */
3667 nameptr++;
3668 continue;
3670 /* find the next / */
3671 if ((name_end = strchr(nameptr, '/')) != NULL)
3673 *name_end = 0;
3676 /* oops - the last check for a / didn't find one. */
3677 if (name_end == NULL)
3678 break;
3680 (*ppname_array)[i].is_wild = ((strchr( nameptr, '?')!=NULL) ||
3681 (strchr( nameptr, '*')!=NULL));
3682 if(((*ppname_array)[i].name = strdup(nameptr)) == NULL)
3684 DEBUG(0,("set_namearray: malloc fail (1)\n"));
3685 return;
3688 /* next segment please */
3689 nameptr = name_end + 1;
3690 i++;
3693 (*ppname_array)[i].name = NULL;
3695 return;
3698 /****************************************************************************
3699 routine to free a namearray.
3700 ****************************************************************************/
3702 void free_namearray(name_compare_entry *name_array)
3704 if(name_array == 0)
3705 return;
3707 if(name_array->name != NULL)
3708 free(name_array->name);
3710 free((char *)name_array);
3713 /****************************************************************************
3714 routine to do file locking
3715 ****************************************************************************/
3716 BOOL fcntl_lock(int fd,int op,uint32 offset,uint32 count,int type)
3718 #if HAVE_FCNTL_LOCK
3719 struct flock lock;
3720 int ret;
3722 #if 1
3723 uint32 mask = 0xC0000000;
3725 /* make sure the count is reasonable, we might kill the lockd otherwise */
3726 count &= ~mask;
3728 /* the offset is often strange - remove 2 of its bits if either of
3729 the top two bits are set. Shift the top ones by two bits. This
3730 still allows OLE2 apps to operate, but should stop lockd from
3731 dieing */
3732 if ((offset & mask) != 0)
3733 offset = (offset & ~mask) | ((offset & mask) >> 2);
3734 #else
3735 uint32 mask = ((unsigned)1<<31);
3737 /* interpret negative counts as large numbers */
3738 if (count < 0)
3739 count &= ~mask;
3741 /* no negative offsets */
3742 offset &= ~mask;
3744 /* count + offset must be in range */
3745 while ((offset < 0 || (offset + count < 0)) && mask)
3747 offset &= ~mask;
3748 mask = mask >> 1;
3750 #endif
3753 DEBUG(5,("fcntl_lock %d %d %d %d %d\n",fd,op,(int)offset,(int)count,type));
3755 lock.l_type = type;
3756 lock.l_whence = SEEK_SET;
3757 lock.l_start = (int)offset;
3758 lock.l_len = (int)count;
3759 lock.l_pid = 0;
3761 errno = 0;
3763 ret = fcntl(fd,op,&lock);
3765 if (errno != 0)
3766 DEBUG(3,("fcntl lock gave errno %d (%s)\n",errno,strerror(errno)));
3768 /* a lock query */
3769 if (op == F_GETLK)
3771 if ((ret != -1) &&
3772 (lock.l_type != F_UNLCK) &&
3773 (lock.l_pid != 0) &&
3774 (lock.l_pid != getpid()))
3776 DEBUG(3,("fd %d is locked by pid %d\n",fd,lock.l_pid));
3777 return(True);
3780 /* it must be not locked or locked by me */
3781 return(False);
3784 /* a lock set or unset */
3785 if (ret == -1)
3787 DEBUG(3,("lock failed at offset %d count %d op %d type %d (%s)\n",
3788 offset,count,op,type,strerror(errno)));
3790 /* perhaps it doesn't support this sort of locking?? */
3791 if (errno == EINVAL)
3793 DEBUG(3,("locking not supported? returning True\n"));
3794 return(True);
3797 return(False);
3800 /* everything went OK */
3801 DEBUG(5,("Lock call successful\n"));
3803 return(True);
3804 #else
3805 return(False);
3806 #endif
3809 /*******************************************************************
3810 lock a file - returning a open file descriptor or -1 on failure
3811 The timeout is in seconds. 0 means no timeout
3812 ********************************************************************/
3813 int file_lock(char *name,int timeout)
3815 int fd = open(name,O_RDWR|O_CREAT,0666);
3816 time_t t=0;
3817 if (fd < 0) return(-1);
3819 #if HAVE_FCNTL_LOCK
3820 if (timeout) t = time(NULL);
3821 while (!timeout || (time(NULL)-t < timeout)) {
3822 if (fcntl_lock(fd,F_SETLK,0,1,F_WRLCK)) return(fd);
3823 msleep(LOCK_RETRY_TIMEOUT);
3825 return(-1);
3826 #else
3827 return(fd);
3828 #endif
3831 /*******************************************************************
3832 unlock a file locked by file_lock
3833 ********************************************************************/
3834 void file_unlock(int fd)
3836 if (fd<0) return;
3837 #if HAVE_FCNTL_LOCK
3838 fcntl_lock(fd,F_SETLK,0,1,F_UNLCK);
3839 #endif
3840 close(fd);
3843 /*******************************************************************
3844 is the name specified one of my netbios names
3845 returns true is it is equal, false otherwise
3846 ********************************************************************/
3847 BOOL is_myname(const char *s)
3849 int n;
3850 BOOL ret = False;
3852 for (n=0; my_netbios_names[n]; n++) {
3853 if (strequal(my_netbios_names[n], s))
3854 ret=True;
3856 DEBUG(8, ("is_myname(\"%s\") returns %d\n", s, ret));
3857 return(ret);