smbfs/helpers: Comment/remove unused code. Reduce .data
[midnight-commander.git] / src / vfs / smbfs / helpers / lib / util.c
blob97afceb520742e3bfa7f2686669c367d301b15bb
1 /*
2 Unix SMB/Netbios implementation.
3 Version 1.9.
4 Samba utility functions
6 Copyright (C) Andrew Tridgell 1992-1998
8 Copyright (C) 2011-2018
9 Free Software Foundation, Inc.
11 This file is part of the Midnight Commander.
13 The Midnight Commander is free software: you can redistribute it
14 and/or modify it under the terms of the GNU General Public License as
15 published by the Free Software Foundation, either version 3 of the License,
16 or (at your option) any later version.
18 The Midnight Commander is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 GNU General Public License for more details.
23 You should have received a copy of the GNU General Public License
24 along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include "includes.h"
29 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
30 #ifdef WITH_NISPLUS_HOME
31 #ifdef BROKEN_NISPLUS_INCLUDE_FILES
33 * The following lines are needed due to buggy include files
34 * in Solaris 2.6 which define GROUP in both /usr/include/sys/acl.h and
35 * also in /usr/include/rpcsvc/nis.h. The definitions conflict. JRA.
36 * Also GROUP_OBJ is defined as 0x4 in /usr/include/sys/acl.h and as
37 * an enum in /usr/include/rpcsvc/nis.h.
40 #if defined(GROUP)
41 #undef GROUP
42 #endif
44 #if defined(GROUP_OBJ)
45 #undef GROUP_OBJ
46 #endif
48 #endif /* BROKEN_NISPLUS_INCLUDE_FILES */
50 #include <rpcsvc/nis.h>
52 #else /* !WITH_NISPLUS_HOME */
54 #include "rpcsvc/ypclnt.h"
56 #endif /* WITH_NISPLUS_HOME */
57 #endif /* HAVE_NETGROUP && WITH_AUTOMOUNT */
59 #ifdef WITH_SSL
60 #include <ssl.h>
61 #undef Realloc /* SSLeay defines this and samba has a function of this name */
62 #endif /* WITH_SSL */
64 extern int DEBUGLEVEL;
65 #if 0
66 int Protocol = PROTOCOL_COREPLUS;
67 #endif /*0 */
69 /* a default finfo structure to ensure all fields are sensible */
70 file_info const def_finfo = { -1, 0, 0, 0, 0, 0, 0, "" };
72 /* the client file descriptor */
73 extern int Client;
75 /* this is used by the chaining code */
76 const int chain_size = 0;
79 case handling on filenames
81 const int case_default = CASE_LOWER;
83 #if 0
84 /* the following control case operations - they are put here so the
85 client can link easily */
86 BOOL case_sensitive;
87 BOOL case_preserve;
88 BOOL use_mangled_map = False;
89 BOOL short_case_preserve;
90 BOOL case_mangle;
91 #endif /*0 */
93 static const char *remote_machine = "";
94 static const char *local_machine = "";
95 static const char *remote_arch = "UNKNOWN";
96 #if 0
97 static enum remote_arch_types ra_type = RA_UNKNOWN;
98 #endif
99 static const char *remote_proto = "UNKNOWN";
100 pstring myhostname = "";
101 pstring user_socket_options = "";
103 static const char sesssetup_user[] = "";
104 static const char *const samlogon_user = "";
106 const BOOL sam_logon_in_ssb = False;
108 pstring global_myname = "";
109 #if 0
110 char **my_netbios_names;
111 #endif /*0 */
114 /****************************************************************************
115 find a suitable temporary directory. The result should be copied immediately
116 as it may be overwritten by a subsequent call
117 ****************************************************************************/
118 const char *
119 tmpdir (void)
121 char *p;
122 if ((p = getenv ("MC_TMPDIR")) || (p = getenv ("TMPDIR")))
124 return p;
126 return "/tmp";
129 /****************************************************************************
130 determine whether we are in the specified group
131 ****************************************************************************/
132 #if 0
133 BOOL
134 in_group (gid_t group, gid_t current_gid, int ngroups, gid_t * groups)
136 int i;
138 if (group == current_gid)
139 return (True);
141 for (i = 0; i < ngroups; i++)
142 if (group == groups[i])
143 return (True);
145 return (False);
149 /****************************************************************************
150 like atoi but gets the value up to the separater character
151 ****************************************************************************/
152 char *
153 Atoic (char *p, int *n, char *c)
155 if (!isdigit ((int) *p))
157 DEBUG (5, ("Atoic: malformed number\n"));
158 return NULL;
161 (*n) = atoi (p);
163 while ((*p) && isdigit ((int) *p))
165 p++;
168 if (strchr (c, *p) == NULL)
170 DEBUG (5, ("Atoic: no separator characters (%s) not found\n", c));
171 return NULL;
174 return p;
177 /*************************************************************************
178 reads a list of numbers
179 *************************************************************************/
180 char *
181 get_numlist (char *p, uint32 ** num, int *count)
183 int val;
185 if (num == NULL || count == NULL)
187 return NULL;
190 (*count) = 0;
191 (*num) = NULL;
193 while ((p = Atoic (p, &val, ":,")) != NULL && (*p) != ':')
195 (*num) = Realloc ((*num), ((*count) + 1) * sizeof (uint32));
196 if ((*num) == NULL)
198 return NULL;
200 (*num)[(*count)] = val;
201 (*count)++;
202 p++;
205 return p;
207 #endif /* 0 */
208 /*******************************************************************
209 copy an IP address from one buffer to another
210 ********************************************************************/
211 void
212 putip (void *dest, void *src)
214 memcpy (dest, src, 4);
218 #define TRUNCATE_NETBIOS_NAME 1
219 #if 0
220 /*******************************************************************
221 convert, possibly using a stupid microsoft-ism which has destroyed
222 the transport independence of netbios (for CIFS vendors that usually
223 use the Win95-type methods, not for NT to NT communication, which uses
224 DCE/RPC and therefore full-length unicode strings...) a dns name into
225 a netbios name.
227 the netbios name (NOT necessarily null-terminated) is truncated to 15
228 characters.
230 ******************************************************************/
231 char *
232 dns_to_netbios_name (char *dns_name)
234 static char netbios_name[16];
235 int i;
236 StrnCpy (netbios_name, dns_name, 15);
237 netbios_name[15] = 0;
239 #ifdef TRUNCATE_NETBIOS_NAME
240 /* ok. this is because of a stupid microsoft-ism. if the called host
241 name contains a '.', microsoft clients expect you to truncate the
242 netbios name up to and including the '.' this even applies, by
243 mistake, to workgroup (domain) names, which is _really_ daft.
245 for (i = 15; i >= 0; i--)
247 if (netbios_name[i] == '.')
249 netbios_name[i] = 0;
250 break;
253 #endif /* TRUNCATE_NETBIOS_NAME */
255 return netbios_name;
259 /****************************************************************************
260 interpret the weird netbios "name". Return the name type
261 ****************************************************************************/
262 static int
263 name_interpret (char *in, char *out)
265 int ret;
266 int len = (*in++) / 2;
268 *out = 0;
270 if (len > 30 || len < 1)
271 return (0);
273 while (len--)
275 if (in[0] < 'A' || in[0] > 'P' || in[1] < 'A' || in[1] > 'P')
277 *out = 0;
278 return (0);
280 *out = ((in[0] - 'A') << 4) + (in[1] - 'A');
281 in += 2;
282 out++;
284 *out = 0;
285 ret = out[-1];
287 #ifdef NETBIOS_SCOPE
288 /* Handle any scope names */
289 while (*in)
291 *out++ = '.'; /* Scope names are separated by periods */
292 len = *(unsigned char *) in++;
293 StrnCpy (out, in, len);
294 out += len;
295 *out = 0;
296 in += len;
298 #endif
299 return (ret);
301 #endif /* 0 */
303 /****************************************************************************
304 mangle a name into netbios format
306 Note: <Out> must be (33 + strlen(scope) + 2) bytes long, at minimum.
307 ****************************************************************************/
309 name_mangle (char *In, char *Out, char name_type)
311 int i;
312 int c;
313 int len;
314 char buf[20];
315 char *p = Out;
316 extern pstring global_scope;
318 /* Safely copy the input string, In, into buf[]. */
319 (void) memset (buf, 0, 20);
320 if (strcmp (In, "*") == 0)
321 buf[0] = '*';
322 else
323 (void) slprintf (buf, sizeof (buf) - 1, "%-15.15s%c", In, name_type);
325 /* Place the length of the first field into the output buffer. */
326 p[0] = 32;
327 p++;
329 /* Now convert the name to the rfc1001/1002 format. */
330 for (i = 0; i < 16; i++)
332 c = toupper (buf[i]);
333 p[i * 2] = ((c >> 4) & 0x000F) + 'A';
334 p[(i * 2) + 1] = (c & 0x000F) + 'A';
336 p += 32;
337 p[0] = '\0';
339 /* Add the scope string. */
340 for (i = 0, len = 0;; i++, len++)
342 switch (global_scope[i])
344 case '\0':
345 p[0] = len;
346 if (len > 0)
347 p[len + 1] = 0;
348 return (name_len (Out));
349 case '.':
350 p[0] = len;
351 p += (len + 1);
352 len = -1;
353 break;
354 default:
355 p[len + 1] = global_scope[i];
356 break;
360 return (name_len (Out));
361 } /* name_mangle */
363 /*******************************************************************
364 check if a file exists
365 ********************************************************************/
366 BOOL
367 file_exist (char *fname, SMB_STRUCT_STAT * sbuf)
369 SMB_STRUCT_STAT st;
370 if (!sbuf)
371 sbuf = &st;
373 if (sys_stat (fname, sbuf) != 0)
374 return (False);
376 return (S_ISREG (sbuf->st_mode));
379 /*******************************************************************
380 check a files mod time
381 ********************************************************************/
382 time_t
383 file_modtime (char *fname)
385 SMB_STRUCT_STAT st;
387 if (sys_stat (fname, &st) != 0)
388 return (0);
390 return (st.st_mtime);
393 #if 0
394 /*******************************************************************
395 check if a directory exists
396 ********************************************************************/
397 BOOL
398 directory_exist (char *dname, SMB_STRUCT_STAT * st)
400 SMB_STRUCT_STAT st2;
401 BOOL ret;
403 if (!st)
404 st = &st2;
406 if (sys_stat (dname, st) != 0)
407 return (False);
409 ret = S_ISDIR (st->st_mode);
410 if (!ret)
411 errno = ENOTDIR;
412 return ret;
415 /*******************************************************************
416 returns the size in bytes of the named file
417 ********************************************************************/
418 SMB_OFF_T
419 file_size (char *file_name)
421 SMB_STRUCT_STAT buf;
422 buf.st_size = 0;
423 if (sys_stat (file_name, &buf) != 0)
424 return (SMB_OFF_T) - 1;
425 return (buf.st_size);
427 #endif /* 0 */
429 /*******************************************************************
430 return a string representing an attribute for a file
431 ********************************************************************/
432 char *
433 attrib_string (uint16 mode)
435 static char attrstr[7];
436 int i = 0;
438 attrstr[0] = 0;
440 if (mode & aVOLID)
441 attrstr[i++] = 'V';
442 if (mode & aDIR)
443 attrstr[i++] = 'D';
444 if (mode & aARCH)
445 attrstr[i++] = 'A';
446 if (mode & aHIDDEN)
447 attrstr[i++] = 'H';
448 if (mode & aSYSTEM)
449 attrstr[i++] = 'S';
450 if (mode & aRONLY)
451 attrstr[i++] = 'R';
453 attrstr[i] = 0;
455 return (attrstr);
458 #if 0
459 /****************************************************************************
460 make a file into unix format
461 ****************************************************************************/
462 void
463 unix_format (char *fname)
465 string_replace (fname, '\\', '/');
468 /****************************************************************************
469 make a file into dos format
470 ****************************************************************************/
471 void
472 dos_format (char *fname)
474 string_replace (fname, '/', '\\');
476 #endif /* 0 */
477 /*******************************************************************
478 show a smb message structure
479 ********************************************************************/
480 void
481 show_msg (char *buf)
483 int i;
484 int bcc = 0;
486 if (DEBUGLEVEL < 5)
487 return;
489 DEBUG (5,
490 ("size=%d\nsmb_com=0x%x\nsmb_rcls=%d\nsmb_reh=%d\nsmb_err=%d\nsmb_flg=%d\nsmb_flg2=%d\n",
491 smb_len (buf), (int) CVAL (buf, smb_com), (int) CVAL (buf, smb_rcls), (int) CVAL (buf,
492 smb_reh),
493 (int) SVAL (buf, smb_err), (int) CVAL (buf, smb_flg), (int) SVAL (buf, smb_flg2)));
494 DEBUG (5,
495 ("smb_tid=%d\nsmb_pid=%d\nsmb_uid=%d\nsmb_mid=%d\nsmt_wct=%d\n",
496 (int) SVAL (buf, smb_tid), (int) SVAL (buf, smb_pid), (int) SVAL (buf, smb_uid),
497 (int) SVAL (buf, smb_mid), (int) CVAL (buf, smb_wct)));
499 for (i = 0; i < (int) CVAL (buf, smb_wct); i++)
501 DEBUG (5, ("smb_vwv[%d]=%d (0x%X)\n", i,
502 SVAL (buf, smb_vwv + 2 * i), SVAL (buf, smb_vwv + 2 * i)));
505 bcc = (int) SVAL (buf, smb_vwv + 2 * (CVAL (buf, smb_wct)));
507 DEBUG (5, ("smb_bcc=%d\n", bcc));
509 if (DEBUGLEVEL < 10)
510 return;
512 if (DEBUGLEVEL < 50)
514 bcc = MIN (bcc, 512);
517 dump_data (10, smb_buf (buf), bcc);
520 /*******************************************************************
521 return the length of an smb packet
522 ********************************************************************/
524 smb_len (char *buf)
526 return (PVAL (buf, 3) | (PVAL (buf, 2) << 8) | ((PVAL (buf, 1) & 1) << 16));
529 /*******************************************************************
530 set the length of an smb packet
531 ********************************************************************/
532 void
533 _smb_setlen (char *buf, int len)
535 buf[0] = 0;
536 buf[1] = (len & 0x10000) >> 16;
537 buf[2] = (len & 0xFF00) >> 8;
538 buf[3] = len & 0xFF;
541 /*******************************************************************
542 set the length and marker of an smb packet
543 ********************************************************************/
544 void
545 smb_setlen (char *buf, int len)
547 _smb_setlen (buf, len);
549 CVAL (buf, 4) = 0xFF;
550 CVAL (buf, 5) = 'S';
551 CVAL (buf, 6) = 'M';
552 CVAL (buf, 7) = 'B';
555 /*******************************************************************
556 setup the word count and byte count for a smb message
557 ********************************************************************/
559 set_message (char *buf, int num_words, int num_bytes, BOOL zero)
561 if (zero)
562 memset (buf + smb_size, '\0', num_words * 2 + num_bytes);
563 CVAL (buf, smb_wct) = num_words;
564 SSVAL (buf, smb_vwv + num_words * SIZEOFWORD, num_bytes);
565 smb_setlen (buf, smb_size + num_words * 2 + num_bytes - 4);
566 return (smb_size + num_words * 2 + num_bytes);
569 /*******************************************************************
570 return the number of smb words
571 ********************************************************************/
572 static int
573 smb_numwords (char *buf)
575 return (CVAL (buf, smb_wct));
578 /*******************************************************************
579 return the size of the smb_buf region of a message
580 ********************************************************************/
582 smb_buflen (char *buf)
584 return (SVAL (buf, smb_vwv0 + smb_numwords (buf) * 2));
587 /*******************************************************************
588 return a pointer to the smb_buf data area
589 ********************************************************************/
590 static int
591 smb_buf_ofs (char *buf)
593 return (smb_size + CVAL (buf, smb_wct) * 2);
596 /*******************************************************************
597 return a pointer to the smb_buf data area
598 ********************************************************************/
599 char *
600 smb_buf (char *buf)
602 return (buf + smb_buf_ofs (buf));
605 /*******************************************************************
606 return the SMB offset into an SMB buffer
607 ********************************************************************/
609 smb_offset (char *p, char *buf)
611 return (PTR_DIFF (p, buf + 4) + chain_size);
614 #if 0
615 /*******************************************************************
616 reduce a file name, removing .. elements.
617 ********************************************************************/
618 void
619 dos_clean_name (char *s)
621 char *p = NULL;
623 DEBUG (3, ("dos_clean_name [%s]\n", s));
625 /* remove any double slashes */
626 string_sub (s, "\\\\", "\\");
628 while ((p = strstr (s, "\\..\\")) != NULL)
630 pstring s1;
632 *p = 0;
633 pstrcpy (s1, p + 3);
635 if ((p = strrchr (s, '\\')) != NULL)
636 *p = 0;
637 else
638 *s = 0;
639 pstrcat (s, s1);
642 trim_string (s, NULL, "\\..");
644 string_sub (s, "\\.\\", "\\");
647 /*******************************************************************
648 reduce a file name, removing .. elements.
649 ********************************************************************/
650 void
651 unix_clean_name (char *s)
653 char *p = NULL;
655 DEBUG (3, ("unix_clean_name [%s]\n", s));
657 /* remove any double slashes */
658 string_sub (s, "//", "/");
660 /* Remove leading ./ characters */
661 if (strncmp (s, "./", 2) == 0)
663 trim_string (s, "./", NULL);
664 if (*s == 0)
665 pstrcpy (s, "./");
668 while ((p = strstr (s, "/../")) != NULL)
670 pstring s1;
672 *p = 0;
673 pstrcpy (s1, p + 3);
675 if ((p = strrchr (s, '/')) != NULL)
676 *p = 0;
677 else
678 *s = 0;
679 pstrcat (s, s1);
682 trim_string (s, NULL, "/..");
685 /*******************************************************************
686 reduce a file name, removing .. elements and checking that
687 it is below dir in the heirachy. This uses dos_GetWd() and so must be run
688 on the system that has the referenced file system.
690 widelinks are allowed if widelinks is true
691 ********************************************************************/
692 BOOL
693 reduce_name (char *s, char *dir, BOOL widelinks)
695 #ifndef REDUCE_PATHS
696 return True;
697 #else
698 pstring dir2;
699 pstring wd;
700 pstring base_name;
701 pstring newname;
702 char *p = NULL;
703 BOOL relative = (*s != '/');
705 *dir2 = *wd = *base_name = *newname = 0;
707 if (widelinks)
709 unix_clean_name (s);
710 /* can't have a leading .. */
711 if (strncmp (s, "..", 2) == 0 && (s[2] == 0 || s[2] == '/'))
713 DEBUG (3, ("Illegal file name? (%s)\n", s));
714 return (False);
717 if (strlen (s) == 0)
718 pstrcpy (s, "./");
720 return (True);
723 DEBUG (3, ("reduce_name [%s] [%s]\n", s, dir));
725 /* remove any double slashes */
726 string_sub (s, "//", "/");
728 pstrcpy (base_name, s);
729 p = strrchr (base_name, '/');
731 if (!p)
732 return (True);
734 if (!dos_GetWd (wd))
736 DEBUG (0, ("couldn't getwd for %s %s\n", s, dir));
737 return (False);
740 if (dos_ChDir (dir) != 0)
742 DEBUG (0, ("couldn't chdir to %s\n", dir));
743 return (False);
746 if (!dos_GetWd (dir2))
748 DEBUG (0, ("couldn't getwd for %s\n", dir));
749 dos_ChDir (wd);
750 return (False);
753 if (p && (p != base_name))
755 *p = 0;
756 if (strcmp (p + 1, ".") == 0)
757 p[1] = 0;
758 if (strcmp (p + 1, "..") == 0)
759 *p = '/';
762 if (dos_ChDir (base_name) != 0)
764 dos_ChDir (wd);
765 DEBUG (3, ("couldn't chdir for %s %s basename=%s\n", s, dir, base_name));
766 return (False);
769 if (!dos_GetWd (newname))
771 dos_ChDir (wd);
772 DEBUG (2, ("couldn't get wd for %s %s\n", s, dir2));
773 return (False);
776 if (p && (p != base_name))
778 pstrcat (newname, "/");
779 pstrcat (newname, p + 1);
783 size_t l = strlen (dir2);
784 if (dir2[l - 1] == '/')
785 l--;
787 if (strncmp (newname, dir2, l) != 0)
789 dos_ChDir (wd);
790 DEBUG (2,
791 ("Bad access attempt? s=%s dir=%s newname=%s l=%d\n", s, dir2, newname,
792 (int) l));
793 return (False);
796 if (relative)
798 if (newname[l] == '/')
799 pstrcpy (s, newname + l + 1);
800 else
801 pstrcpy (s, newname + l);
803 else
804 pstrcpy (s, newname);
807 dos_ChDir (wd);
809 if (strlen (s) == 0)
810 pstrcpy (s, "./");
812 DEBUG (3, ("reduced to %s\n", s));
813 return (True);
814 #endif
818 /****************************************************************************
819 expand some *s
820 ****************************************************************************/
821 static void
822 expand_one (char *Mask, int len)
824 char *p1;
825 while ((p1 = strchr (Mask, '*')) != NULL)
827 int lfill = (len + 1) - strlen (Mask);
828 int l1 = (p1 - Mask);
829 pstring tmp;
830 pstrcpy (tmp, Mask);
831 memset (tmp + l1, '?', lfill);
832 pstrcpy (tmp + l1 + lfill, Mask + l1 + 1);
833 pstrcpy (Mask, tmp);
837 /****************************************************************************
838 parse out a directory name from a path name. Assumes dos style filenames.
839 ****************************************************************************/
840 static void
841 dirname_dos (char *path, char *buf)
843 split_at_last_component (path, buf, '\\', NULL);
847 /****************************************************************************
848 parse out a filename from a path name. Assumes dos style filenames.
849 ****************************************************************************/
850 static char *
851 filename_dos (char *path, char *buf)
853 char *p = strrchr (path, '\\');
855 if (!p)
856 pstrcpy (buf, path);
857 else
858 pstrcpy (buf, p + 1);
860 return (buf);
863 /****************************************************************************
864 expand a wildcard expression, replacing *s with ?s
865 ****************************************************************************/
866 void
867 expand_mask (char *Mask, BOOL doext)
869 pstring mbeg, mext;
870 pstring dirpart;
871 pstring filepart;
872 BOOL hasdot = False;
873 char *p1;
874 BOOL absolute = (*Mask == '\\');
876 *mbeg = *mext = *dirpart = *filepart = 0;
878 /* parse the directory and filename */
879 if (strchr (Mask, '\\'))
880 dirname_dos (Mask, dirpart);
882 filename_dos (Mask, filepart);
884 pstrcpy (mbeg, filepart);
885 if ((p1 = strchr (mbeg, '.')) != NULL)
887 hasdot = True;
888 *p1 = 0;
889 p1++;
890 pstrcpy (mext, p1);
892 else
894 pstrcpy (mext, "");
895 if (strlen (mbeg) > 8)
897 pstrcpy (mext, mbeg + 8);
898 mbeg[8] = 0;
902 if (*mbeg == 0)
903 pstrcpy (mbeg, "????????");
904 if ((*mext == 0) && doext && !hasdot)
905 pstrcpy (mext, "???");
907 if (strequal (mbeg, "*") && *mext == 0)
908 pstrcpy (mext, "*");
910 /* expand *'s */
911 expand_one (mbeg, 8);
912 if (*mext)
913 expand_one (mext, 3);
915 pstrcpy (Mask, dirpart);
916 if (*dirpart || absolute)
917 pstrcat (Mask, "\\");
918 pstrcat (Mask, mbeg);
919 pstrcat (Mask, ".");
920 pstrcat (Mask, mext);
922 DEBUG (6, ("Mask expanded to [%s]\n", Mask));
926 /****************************************************************************
927 make a dir struct
928 ****************************************************************************/
929 void
930 make_dir_struct (char *buf, char *mask, char *fname, SMB_OFF_T size, int mode, time_t date)
932 char *p;
933 pstring mask2;
935 pstrcpy (mask2, mask);
937 if ((mode & aDIR) != 0)
938 size = 0;
940 memset (buf + 1, ' ', 11);
941 if ((p = strchr (mask2, '.')) != NULL)
943 *p = 0;
944 memcpy (buf + 1, mask2, MIN (strlen (mask2), 8));
945 memcpy (buf + 9, p + 1, MIN (strlen (p + 1), 3));
946 *p = '.';
948 else
949 memcpy (buf + 1, mask2, MIN (strlen (mask2), 11));
951 memset (buf + 21, '\0', DIR_STRUCT_SIZE - 21);
952 CVAL (buf, 21) = mode;
953 put_dos_date (buf, 22, date);
954 SSVAL (buf, 26, size & 0xFFFF);
955 SSVAL (buf, 28, (size >> 16) & 0xFFFF);
956 StrnCpy (buf + 30, fname, 12);
957 if (!case_sensitive)
958 strupper (buf + 30);
959 DEBUG (8, ("put name [%s] into dir struct\n", buf + 30));
963 /*******************************************************************
964 close the low 3 fd's and open dev/null in their place
965 ********************************************************************/
966 void
967 close_low_fds (void)
969 int fd;
970 int i;
971 close (0);
972 close (1);
973 close (2);
974 /* try and use up these file descriptors, so silly
975 library routines writing to stdout etc won't cause havoc */
976 for (i = 0; i < 3; i++)
978 fd = sys_open ("/dev/null", O_RDWR, 0);
979 if (fd < 0)
980 fd = sys_open ("/dev/null", O_WRONLY, 0);
981 if (fd < 0)
983 DEBUG (0, ("Cannot open /dev/null\n"));
984 return;
986 if (fd != i)
988 DEBUG (0, ("Didn't get file descriptor %d\n", i));
989 return;
993 #endif /* 0 */
995 /****************************************************************************
996 Set a fd into blocking/nonblocking mode. Uses POSIX O_NONBLOCK if available,
997 else
998 if SYSV use O_NDELAY
999 if BSD use FNDELAY
1000 ****************************************************************************/
1002 set_blocking (int fd, BOOL set)
1004 int val;
1005 #ifdef O_NONBLOCK
1006 #define FLAG_TO_SET O_NONBLOCK
1007 #else
1008 #ifdef SYSV
1009 #define FLAG_TO_SET O_NDELAY
1010 #else /* BSD */
1011 #define FLAG_TO_SET FNDELAY
1012 #endif
1013 #endif
1015 if ((val = fcntl (fd, F_GETFL, 0)) == -1)
1016 return -1;
1017 if (set) /* Turn blocking on - ie. clear nonblock flag */
1018 val &= ~FLAG_TO_SET;
1019 else
1020 val |= FLAG_TO_SET;
1021 return fcntl (fd, F_SETFL, val);
1022 #undef FLAG_TO_SET
1026 /*******************************************************************
1027 find the difference in milliseconds between two struct timeval
1028 values
1029 ********************************************************************/
1031 TvalDiff (struct timeval *tvalold, struct timeval *tvalnew)
1033 return ((tvalnew->tv_sec - tvalold->tv_sec) * 1000 +
1034 ((int) tvalnew->tv_usec - (int) tvalold->tv_usec) / 1000);
1038 #if 0
1039 /****************************************************************************
1040 transfer some data between two fd's
1041 ****************************************************************************/
1042 SMB_OFF_T
1043 transfer_file (int infd, int outfd, SMB_OFF_T n, char *header, int headlen, int align)
1045 static char *buf = NULL;
1046 static int size = 0;
1047 char *buf1, *abuf;
1048 SMB_OFF_T total = 0;
1050 DEBUG (4, ("transfer_file n=%.0f (head=%d) called\n", (double) n, headlen));
1052 if (size == 0)
1054 size = lp_readsize ();
1055 size = MAX (size, 1024);
1058 while (!buf && size > 0)
1060 buf = (char *) Realloc (buf, size + 8);
1061 if (!buf)
1062 size /= 2;
1065 if (!buf)
1067 DEBUG (0, ("Cannot allocate transfer buffer!\n"));
1068 exit (1);
1071 abuf = buf + (align % 8);
1073 if (header)
1074 n += headlen;
1076 while (n > 0)
1078 int s = (int) MIN (n, (SMB_OFF_T) size);
1079 int ret, ret2 = 0;
1081 ret = 0;
1083 if (header && (headlen >= MIN (s, 1024)))
1085 buf1 = header;
1086 s = headlen;
1087 ret = headlen;
1088 headlen = 0;
1089 header = NULL;
1091 else
1093 buf1 = abuf;
1096 if (header && headlen > 0)
1098 ret = MIN (headlen, size);
1099 memcpy (buf1, header, ret);
1100 headlen -= ret;
1101 header += ret;
1102 if (headlen <= 0)
1103 header = NULL;
1106 if (s > ret)
1107 ret += read (infd, buf1 + ret, s - ret);
1109 if (ret > 0)
1111 ret2 = (outfd >= 0 ? write_data (outfd, buf1, ret) : ret);
1112 if (ret2 > 0)
1113 total += ret2;
1114 /* if we can't write then dump excess data */
1115 if (ret2 != ret)
1116 transfer_file (infd, -1, n - (ret + headlen), NULL, 0, 0);
1118 if (ret <= 0 || ret2 != ret)
1119 return (total);
1120 n -= ret;
1122 return (total);
1126 /****************************************************************************
1127 find a pointer to a netbios name
1128 ****************************************************************************/
1129 static char *
1130 name_ptr (char *buf, int ofs)
1132 unsigned char c = *(unsigned char *) (buf + ofs);
1134 if ((c & 0xC0) == 0xC0)
1136 uint16 l;
1137 char p[2];
1138 memcpy (p, buf + ofs, 2);
1139 p[0] &= ~0xC0;
1140 l = RSVAL (p, 0);
1141 DEBUG (5, ("name ptr to pos %d from %d is %s\n", l, ofs, buf + l));
1142 return (buf + l);
1144 else
1145 return (buf + ofs);
1148 /****************************************************************************
1149 extract a netbios name from a buf
1150 ****************************************************************************/
1152 name_extract (char *buf, int ofs, char *name)
1154 char *p = name_ptr (buf, ofs);
1155 int d = PTR_DIFF (p, buf + ofs);
1156 pstrcpy (name, "");
1157 if (d < -50 || d > 50)
1158 return (0);
1159 return (name_interpret (p, name));
1161 #endif /* 0 */
1163 /****************************************************************************
1164 return the total storage length of a mangled name
1165 ****************************************************************************/
1167 name_len (char *s1)
1169 /* NOTE: this argument _must_ be unsigned */
1170 unsigned char *s = (unsigned char *) s1;
1171 int len;
1173 /* If the two high bits of the byte are set, return 2. */
1174 if (0xC0 == (*s & 0xC0))
1175 return (2);
1177 /* Add up the length bytes. */
1178 for (len = 1; (*s); s += (*s) + 1)
1180 len += *s + 1;
1181 SMB_ASSERT (len < 80);
1184 return (len);
1185 } /* name_len */
1188 /*******************************************************************
1189 sleep for a specified number of milliseconds
1190 ********************************************************************/
1191 void
1192 msleep (int t)
1194 int tdiff = 0;
1195 struct timeval tval, t1, t2;
1196 fd_set fds;
1198 GetTimeOfDay (&t1);
1199 GetTimeOfDay (&t2);
1201 while (tdiff < t)
1203 tval.tv_sec = (t - tdiff) / 1000;
1204 tval.tv_usec = 1000 * ((t - tdiff) % 1000);
1206 FD_ZERO (&fds);
1207 errno = 0;
1208 sys_select (0, &fds, &tval);
1210 GetTimeOfDay (&t2);
1211 tdiff = TvalDiff (&t1, &t2);
1215 #if 0
1216 /*********************************************************
1217 * Recursive routine that is called by unix_mask_match.
1218 * Does the actual matching. This is the 'original code'
1219 * used by the unix matcher.
1220 *********************************************************/
1221 static BOOL
1222 unix_do_match (char *str, char *regexp, int case_sig)
1224 char *p;
1226 for (p = regexp; *p && *str;)
1228 switch (*p)
1230 case '?':
1231 str++;
1232 p++;
1233 break;
1235 case '*':
1236 /* Look for a character matching
1237 the one after the '*' */
1238 p++;
1239 if (!*p)
1240 return True; /* Automatic match */
1241 while (*str)
1243 while (*str && (case_sig ? (*p != *str) : (toupper (*p) != toupper (*str))))
1244 str++;
1245 if (unix_do_match (str, p, case_sig))
1246 return True;
1247 if (!*str)
1248 return False;
1249 else
1250 str++;
1252 return False;
1254 default:
1255 if (case_sig)
1257 if (*str != *p)
1258 return False;
1260 else
1262 if (toupper (*str) != toupper (*p))
1263 return False;
1265 str++, p++;
1266 break;
1269 if (!*p && !*str)
1270 return True;
1272 if (!*p && str[0] == '.' && str[1] == 0)
1273 return (True);
1275 if (!*str && *p == '?')
1277 while (*p == '?')
1278 p++;
1279 return (!*p);
1282 if (!*str && (*p == '*' && p[1] == '\0'))
1283 return True;
1284 return False;
1288 /*********************************************************
1289 * Routine to match a given string with a regexp - uses
1290 * simplified regexp that takes * and ? only. Case can be
1291 * significant or not.
1292 * This is the 'original code' used by the unix matcher.
1293 *********************************************************/
1295 static BOOL
1296 unix_mask_match (char *str, char *regexp, int case_sig, BOOL trans2)
1298 char *p;
1299 pstring p1, p2;
1300 fstring ebase, eext, sbase, sext;
1302 BOOL matched;
1304 /* Make local copies of str and regexp */
1305 StrnCpy (p1, regexp, sizeof (pstring) - 1);
1306 StrnCpy (p2, str, sizeof (pstring) - 1);
1308 if (!strchr (p2, '.'))
1310 pstrcat (p2, ".");
1313 /* Remove any *? and ** as they are meaningless */
1314 for (p = p1; *p; p++)
1315 while (*p == '*' && (p[1] == '?' || p[1] == '*'))
1316 (void) pstrcpy (&p[1], &p[2]);
1318 if (strequal (p1, "*"))
1319 return (True);
1321 DEBUG (8, ("unix_mask_match str=<%s> regexp=<%s>, case_sig = %d\n", p2, p1, case_sig));
1323 if (trans2)
1325 fstrcpy (ebase, p1);
1326 fstrcpy (sbase, p2);
1328 else
1330 if ((p = strrchr (p1, '.')))
1332 *p = 0;
1333 fstrcpy (ebase, p1);
1334 fstrcpy (eext, p + 1);
1336 else
1338 fstrcpy (ebase, p1);
1339 eext[0] = 0;
1342 if (!strequal (p2, ".") && !strequal (p2, "..") && (p = strrchr (p2, '.')))
1344 *p = 0;
1345 fstrcpy (sbase, p2);
1346 fstrcpy (sext, p + 1);
1348 else
1350 fstrcpy (sbase, p2);
1351 fstrcpy (sext, "");
1355 matched = unix_do_match (sbase, ebase, case_sig) &&
1356 (trans2 || unix_do_match (sext, eext, case_sig));
1358 DEBUG (8, ("unix_mask_match returning %d\n", matched));
1360 return matched;
1363 /*********************************************************
1364 * Recursive routine that is called by mask_match.
1365 * Does the actual matching. Returns True if matched,
1366 * False if failed. This is the 'new' NT style matcher.
1367 *********************************************************/
1369 BOOL
1370 do_match (char *str, char *regexp, int case_sig)
1372 char *p;
1374 for (p = regexp; *p && *str;)
1376 switch (*p)
1378 case '?':
1379 str++;
1380 p++;
1381 break;
1383 case '*':
1384 /* Look for a character matching
1385 the one after the '*' */
1386 p++;
1387 if (!*p)
1388 return True; /* Automatic match */
1389 while (*str)
1391 while (*str && (case_sig ? (*p != *str) : (toupper (*p) != toupper (*str))))
1392 str++;
1393 /* Now eat all characters that match, as
1394 we want the *last* character to match. */
1395 while (*str && (case_sig ? (*p == *str) : (toupper (*p) == toupper (*str))))
1396 str++;
1397 str--; /* We've eaten the match char after the '*' */
1398 if (do_match (str, p, case_sig))
1400 return True;
1402 if (!*str)
1404 return False;
1406 else
1408 str++;
1411 return False;
1413 default:
1414 if (case_sig)
1416 if (*str != *p)
1418 return False;
1421 else
1423 if (toupper (*str) != toupper (*p))
1425 return False;
1428 str++, p++;
1429 break;
1433 if (!*p && !*str)
1434 return True;
1436 if (!*p && str[0] == '.' && str[1] == 0)
1438 return (True);
1441 if (!*str && *p == '?')
1443 while (*p == '?')
1444 p++;
1445 return (!*p);
1448 if (!*str && (*p == '*' && p[1] == '\0'))
1450 return True;
1453 return False;
1457 /*********************************************************
1458 * Routine to match a given string with a regexp - uses
1459 * simplified regexp that takes * and ? only. Case can be
1460 * significant or not.
1461 * The 8.3 handling was rewritten by Ums Harald <Harald.Ums@pro-sieben.de>
1462 * This is the new 'NT style' matcher.
1463 *********************************************************/
1465 BOOL
1466 mask_match (char *str, char *regexp, int case_sig, BOOL trans2)
1468 char *p;
1469 pstring t_pattern, t_filename, te_pattern, te_filename;
1470 fstring ebase, eext, sbase, sext;
1472 BOOL matched = False;
1474 /* Make local copies of str and regexp */
1475 pstrcpy (t_pattern, regexp);
1476 pstrcpy (t_filename, str);
1478 if (trans2)
1481 /* a special case for 16 bit apps */
1482 if (strequal (t_pattern, "????????.???"))
1483 pstrcpy (t_pattern, "*");
1485 #if 0
1487 * Handle broken clients that send us old 8.3 format.
1489 string_sub (t_pattern, "????????", "*");
1490 string_sub (t_pattern, ".???", ".*");
1491 #endif
1494 #if 0
1496 * Not sure if this is a good idea. JRA.
1498 if (trans2 && is_8_3 (t_pattern, False) && is_8_3 (t_filename, False))
1499 trans2 = False;
1500 #endif
1502 #if 0
1503 if (!strchr (t_filename, '.'))
1505 pstrcat (t_filename, ".");
1507 #endif
1509 /* Remove any *? and ** as they are meaningless */
1510 string_sub (t_pattern, "*?", "*");
1511 string_sub (t_pattern, "**", "*");
1513 if (strequal (t_pattern, "*"))
1514 return (True);
1516 DEBUG (8,
1517 ("mask_match str=<%s> regexp=<%s>, case_sig = %d\n", t_filename, t_pattern, case_sig));
1519 if (trans2)
1522 * Match each component of the regexp, split up by '.'
1523 * characters.
1525 char *fp, *rp, *cp2, *cp1;
1526 BOOL last_wcard_was_star = False;
1527 int num_path_components, num_regexp_components;
1529 pstrcpy (te_pattern, t_pattern);
1530 pstrcpy (te_filename, t_filename);
1532 * Remove multiple "*." patterns.
1534 string_sub (te_pattern, "*.*.", "*.");
1535 num_regexp_components = count_chars (te_pattern, '.');
1536 num_path_components = count_chars (te_filename, '.');
1539 * Check for special 'hack' case of "DIR a*z". - needs to match a.b.c...z
1541 if (num_regexp_components == 0)
1542 matched = do_match (te_filename, te_pattern, case_sig);
1543 else
1545 for (cp1 = te_pattern, cp2 = te_filename; cp1;)
1547 fp = strchr (cp2, '.');
1548 if (fp)
1549 *fp = '\0';
1550 rp = strchr (cp1, '.');
1551 if (rp)
1552 *rp = '\0';
1554 if (cp1[strlen (cp1) - 1] == '*')
1555 last_wcard_was_star = True;
1556 else
1557 last_wcard_was_star = False;
1559 if (!do_match (cp2, cp1, case_sig))
1560 break;
1562 cp1 = rp ? rp + 1 : NULL;
1563 cp2 = fp ? fp + 1 : "";
1565 if (last_wcard_was_star || ((cp1 != NULL) && (*cp1 == '*')))
1567 /* Eat the extra path components. */
1568 int i;
1570 for (i = 0; i < num_path_components - num_regexp_components; i++)
1572 fp = strchr (cp2, '.');
1573 if (fp)
1574 *fp = '\0';
1576 if ((cp1 != NULL) && do_match (cp2, cp1, case_sig))
1578 cp2 = fp ? fp + 1 : "";
1579 break;
1581 cp2 = fp ? fp + 1 : "";
1583 num_path_components -= i;
1586 if (cp1 == NULL && ((*cp2 == '\0') || last_wcard_was_star))
1587 matched = True;
1590 else
1593 /* -------------------------------------------------
1594 * Behaviour of Win95
1595 * for 8.3 filenames and 8.3 Wildcards
1596 * -------------------------------------------------
1598 if (strequal (t_filename, "."))
1601 * Patterns: *.* *. ?. ? ????????.??? are valid.
1604 if (strequal (t_pattern, "*.*") || strequal (t_pattern, "*.") ||
1605 strequal (t_pattern, "????????.???") ||
1606 strequal (t_pattern, "?.") || strequal (t_pattern, "?"))
1607 matched = True;
1609 else if (strequal (t_filename, ".."))
1612 * Patterns: *.* *. ?. ? *.? ????????.??? are valid.
1615 if (strequal (t_pattern, "*.*") || strequal (t_pattern, "*.") ||
1616 strequal (t_pattern, "?.") || strequal (t_pattern, "?") ||
1617 strequal (t_pattern, "????????.???") ||
1618 strequal (t_pattern, "*.?") || strequal (t_pattern, "?.*"))
1619 matched = True;
1621 else
1624 if ((p = strrchr (t_pattern, '.')))
1627 * Wildcard has a suffix.
1629 *p = 0;
1630 fstrcpy (ebase, t_pattern);
1631 if (p[1])
1633 fstrcpy (eext, p + 1);
1635 else
1637 /* pattern ends in DOT: treat as if there is no DOT */
1638 *eext = 0;
1639 if (strequal (ebase, "*"))
1640 return (True);
1643 else
1646 * No suffix for wildcard.
1648 fstrcpy (ebase, t_pattern);
1649 eext[0] = 0;
1652 p = strrchr (t_filename, '.');
1653 if (p && (p[1] == 0))
1656 * Filename has an extension of '.' only.
1658 *p = 0; /* nuke dot at end of string */
1659 p = 0; /* and treat it as if there is no extension */
1662 if (p)
1665 * Filename has an extension.
1667 *p = 0;
1668 fstrcpy (sbase, t_filename);
1669 fstrcpy (sext, p + 1);
1670 if (*eext)
1672 matched = do_match (sbase, ebase, case_sig) && do_match (sext, eext, case_sig);
1674 else
1676 /* pattern has no extension */
1677 /* Really: match complete filename with pattern ??? means exactly 3 chars */
1678 matched = do_match (str, ebase, case_sig);
1681 else
1684 * Filename has no extension.
1686 fstrcpy (sbase, t_filename);
1687 fstrcpy (sext, "");
1688 if (*eext)
1690 /* pattern has extension */
1691 matched = do_match (sbase, ebase, case_sig) && do_match (sext, eext, case_sig);
1693 else
1695 matched = do_match (sbase, ebase, case_sig);
1696 #ifdef EMULATE_WEIRD_W95_MATCHING
1698 * Even Microsoft has some problems
1699 * Behaviour Win95 -> local disk
1700 * is different from Win95 -> smb drive from Nt 4.0
1701 * This branch would reflect the Win95 local disk behaviour
1703 if (!matched)
1705 /* a? matches aa and a in w95 */
1706 fstrcat (sbase, ".");
1707 matched = do_match (sbase, ebase, case_sig);
1709 #endif
1715 DEBUG (8, ("mask_match returning %d\n", matched));
1717 return matched;
1719 #endif /* 0 */
1721 #if 0
1722 /****************************************************************************
1723 set the length of a file from a filedescriptor.
1724 Returns 0 on success, -1 on failure.
1725 ****************************************************************************/
1728 set_filelen (int fd, SMB_OFF_T len)
1730 /* According to W. R. Stevens advanced UNIX prog. Pure 4.3 BSD cannot
1731 extend a file with ftruncate. Provide alternate implementation
1732 for this */
1734 #ifdef HAVE_FTRUNCATE_EXTEND
1735 return sys_ftruncate (fd, len);
1736 #else
1737 SMB_STRUCT_STAT st;
1738 char c = 0;
1739 SMB_OFF_T currpos = sys_lseek (fd, (SMB_OFF_T) 0, SEEK_CUR);
1741 if (currpos == -1)
1742 return -1;
1743 /* Do an fstat to see if the file is longer than
1744 the requested size (call ftruncate),
1745 or shorter, in which case seek to len - 1 and write 1
1746 byte of zero */
1747 if (sys_fstat (fd, &st) < 0)
1748 return -1;
1750 #ifdef S_ISFIFO
1751 if (S_ISFIFO (st.st_mode))
1752 return 0;
1753 #endif
1755 if (st.st_size == len)
1756 return 0;
1757 if (st.st_size > len)
1758 return sys_ftruncate (fd, len);
1760 if (sys_lseek (fd, len - 1, SEEK_SET) != len - 1)
1761 return -1;
1762 if (write (fd, &c, 1) != 1)
1763 return -1;
1764 /* Seek to where we were */
1765 if (sys_lseek (fd, currpos, SEEK_SET) != currpos)
1766 return -1;
1767 return 0;
1768 #endif
1772 #ifdef HPUX
1773 /****************************************************************************
1774 this is a version of setbuffer() for those machines that only have setvbuf
1775 ****************************************************************************/
1776 void
1777 setbuffer (FILE * f, char *buf, int bufsize)
1779 setvbuf (f, buf, _IOFBF, bufsize);
1781 #endif
1782 #endif /* 0 */
1786 /****************************************************************************
1787 expand a pointer to be a particular size
1788 ****************************************************************************/
1789 void *
1790 Realloc (void *p, size_t size)
1792 void *ret = NULL;
1794 if (size == 0)
1796 if (p)
1797 free (p);
1798 DEBUG (5, ("Realloc asked for 0 bytes\n"));
1799 return NULL;
1802 if (!p)
1803 ret = (void *) malloc (size);
1804 else
1805 ret = (void *) realloc (p, size);
1807 #ifdef MEM_MAN
1809 extern FILE *dbf;
1810 smb_mem_write_info (ret, dbf);
1812 #endif
1814 if (!ret)
1815 DEBUG (0, ("Memory allocation error: failed to expand to %d bytes\n", (int) size));
1817 return (ret);
1821 /****************************************************************************
1822 get my own name and IP
1823 ****************************************************************************/
1824 BOOL
1825 get_myname (char *my_name, struct in_addr * ip)
1827 struct hostent *hp;
1828 pstring hostname;
1830 /* cppcheck-suppress uninitvar */
1831 *hostname = 0;
1833 /* get my host name */
1834 if (gethostname (hostname, sizeof (hostname)) == -1)
1836 DEBUG (0, ("gethostname failed\n"));
1837 return False;
1840 /* Ensure null termination. */
1841 hostname[sizeof (hostname) - 1] = '\0';
1843 /* get host info */
1844 if ((hp = Get_Hostbyname (hostname)) == 0)
1846 DEBUG (0, ("Get_Hostbyname: Unknown host %s\n", hostname));
1847 return False;
1850 if (my_name)
1852 /* split off any parts after an initial . */
1853 char *p = strchr (hostname, '.');
1854 if (p)
1855 *p = 0;
1857 fstrcpy (my_name, hostname);
1860 if (ip)
1861 putip ((char *) ip, (char *) hp->h_addr);
1863 return (True);
1867 /****************************************************************************
1868 true if two IP addresses are equal
1869 ****************************************************************************/
1870 BOOL
1871 ip_equal (struct in_addr ip1, struct in_addr ip2)
1873 uint32 a1, a2;
1874 a1 = ntohl (ip1.s_addr);
1875 a2 = ntohl (ip2.s_addr);
1876 return (a1 == a2);
1879 #if 0 /* May be useful one day */
1880 /****************************************************************************
1881 interpret a protocol description string, with a default
1882 ****************************************************************************/
1884 interpret_protocol (char *str, int def)
1886 if (strequal (str, "NT1"))
1887 return (PROTOCOL_NT1);
1888 if (strequal (str, "LANMAN2"))
1889 return (PROTOCOL_LANMAN2);
1890 if (strequal (str, "LANMAN1"))
1891 return (PROTOCOL_LANMAN1);
1892 if (strequal (str, "CORE"))
1893 return (PROTOCOL_CORE);
1894 if (strequal (str, "COREPLUS"))
1895 return (PROTOCOL_COREPLUS);
1896 if (strequal (str, "CORE+"))
1897 return (PROTOCOL_COREPLUS);
1899 DEBUG (0, ("Unrecognised protocol level %s\n", str));
1901 return (def);
1903 #endif /* 0 */
1905 /****************************************************************************
1906 interpret an internet address or name into an IP address in 4 byte form
1907 ****************************************************************************/
1908 uint32
1909 interpret_addr (const char *str)
1911 struct hostent *hp;
1912 uint32 res;
1913 int i;
1914 BOOL pure_address = True;
1916 if (strcmp (str, "0.0.0.0") == 0)
1917 return (0);
1918 if (strcmp (str, "255.255.255.255") == 0)
1919 return (0xFFFFFFFF);
1921 for (i = 0; pure_address && str[i]; i++)
1922 if (!(isdigit ((int) str[i]) || str[i] == '.'))
1923 pure_address = False;
1925 /* if it's in the form of an IP address then get the lib to interpret it */
1926 if (pure_address)
1928 res = inet_addr (str);
1930 else
1932 /* otherwise assume it's a network name of some sort and use
1933 Get_Hostbyname */
1934 if ((hp = Get_Hostbyname (str)) == 0)
1936 DEBUG (3, ("Get_Hostbyname: Unknown host. %s\n", str));
1937 return 0;
1939 if (hp->h_addr == NULL)
1941 DEBUG (3, ("Get_Hostbyname: host address is invalid for host %s\n", str));
1942 return 0;
1944 putip ((char *) &res, (char *) hp->h_addr);
1947 if (res == (uint32) - 1)
1948 return (0);
1950 return (res);
1953 /*******************************************************************
1954 a convenient addition to interpret_addr()
1955 ******************************************************************/
1956 struct in_addr *
1957 interpret_addr2 (const char *str)
1959 static struct in_addr ret;
1960 uint32 a = interpret_addr (str);
1961 ret.s_addr = a;
1962 return (&ret);
1965 /*******************************************************************
1966 check if an IP is the 0.0.0.0
1967 ******************************************************************/
1968 BOOL
1969 zero_ip (struct in_addr ip)
1971 uint32 a;
1972 putip ((char *) &a, (char *) &ip);
1973 return (a == 0);
1977 /*******************************************************************
1978 matchname - determine if host name matches IP address
1979 ******************************************************************/
1980 BOOL
1981 matchname (char *remotehost, struct in_addr addr)
1983 struct hostent *hp;
1984 int i;
1986 if ((hp = Get_Hostbyname (remotehost)) == 0)
1988 DEBUG (0, ("Get_Hostbyname(%s): lookup failure.\n", remotehost));
1989 return False;
1993 * Make sure that gethostbyname() returns the "correct" host name.
1994 * Unfortunately, gethostbyname("localhost") sometimes yields
1995 * "localhost.domain". Since the latter host name comes from the
1996 * local DNS, we just have to trust it (all bets are off if the local
1997 * DNS is perverted). We always check the address list, though.
2000 if (strcasecmp (remotehost, hp->h_name) && strcasecmp (remotehost, "localhost"))
2002 DEBUG (0, ("host name/name mismatch: %s != %s\n", remotehost, hp->h_name));
2003 return False;
2006 /* Look up the host address in the address list we just got. */
2007 for (i = 0; hp->h_addr_list[i]; i++)
2009 if (memcmp (hp->h_addr_list[i], (caddr_t) & addr, sizeof (addr)) == 0)
2010 return True;
2014 * The host name does not map to the original host address. Perhaps
2015 * someone has compromised a name server. More likely someone botched
2016 * it, but that could be dangerous, too.
2019 DEBUG (0, ("host name/address mismatch: %s != %s\n", inet_ntoa (addr), hp->h_name));
2020 return False;
2024 #if (defined(HAVE_NETGROUP) && defined(WITH_AUTOMOUNT))
2025 /******************************************************************
2026 Remove any mount options such as -rsize=2048,wsize=2048 etc.
2027 Based on a fix from <Thomas.Hepper@icem.de>.
2028 *******************************************************************/
2030 static void
2031 strip_mount_options (pstring * str)
2033 if (**str == '-')
2035 char *p = *str;
2036 while (*p && !isspace (*p))
2037 p++;
2038 while (*p && isspace (*p))
2039 p++;
2040 if (*p)
2042 pstring tmp_str;
2044 pstrcpy (tmp_str, p);
2045 pstrcpy (*str, tmp_str);
2050 /*******************************************************************
2051 Patch from jkf@soton.ac.uk
2052 Split Luke's automount_server into YP lookup and string splitter
2053 so can easily implement automount_path().
2054 As we may end up doing both, cache the last YP result.
2055 *******************************************************************/
2057 #ifdef WITH_NISPLUS_HOME
2058 static char *
2059 automount_lookup (char *user_name)
2061 static fstring last_key = "";
2062 static pstring last_value = "";
2064 char *nis_map = (char *) lp_nis_home_map_name ();
2066 char buffer[NIS_MAXATTRVAL + 1];
2067 nis_result *result;
2068 nis_object *object;
2069 entry_obj *entry;
2071 DEBUG (5, ("NIS+ Domain: %s\n", (char *) nis_local_directory ()));
2073 if (strcmp (user_name, last_key))
2075 slprintf (buffer, sizeof (buffer) - 1, "[%s=%s]%s.%s", "key", user_name, nis_map,
2076 (char *) nis_local_directory ());
2077 DEBUG (5, ("NIS+ querystring: %s\n", buffer));
2079 if (result = nis_list (buffer, RETURN_RESULT, NULL, NULL))
2081 if (result->status != NIS_SUCCESS)
2083 DEBUG (3, ("NIS+ query failed: %s\n", nis_sperrno (result->status)));
2084 fstrcpy (last_key, "");
2085 pstrcpy (last_value, "");
2087 else
2089 object = result->objects.objects_val;
2090 if (object->zo_data.zo_type == ENTRY_OBJ)
2092 entry = &object->zo_data.objdata_u.en_data;
2093 DEBUG (5, ("NIS+ entry type: %s\n", entry->en_type));
2094 DEBUG (3,
2095 ("NIS+ result: %s\n",
2096 entry->en_cols.en_cols_val[1].ec_value.ec_value_val));
2098 pstrcpy (last_value, entry->en_cols.en_cols_val[1].ec_value.ec_value_val);
2099 string_sub (last_value, "&", user_name);
2100 fstrcpy (last_key, user_name);
2104 nis_freeresult (result);
2107 strip_mount_options (&last_value);
2109 DEBUG (4, ("NIS+ Lookup: %s resulted in %s\n", user_name, last_value));
2110 return last_value;
2112 #else /* WITH_NISPLUS_HOME */
2113 static char *
2114 automount_lookup (char *user_name)
2116 static fstring last_key = "";
2117 static pstring last_value = "";
2119 int nis_error; /* returned by yp all functions */
2120 char *nis_result; /* yp_match inits this */
2121 int nis_result_len; /* and set this */
2122 char *nis_domain; /* yp_get_default_domain inits this */
2123 char *nis_map = (char *) lp_nis_home_map_name ();
2125 if ((nis_error = yp_get_default_domain (&nis_domain)) != 0)
2127 DEBUG (3, ("YP Error: %s\n", yperr_string (nis_error)));
2128 return last_value;
2131 DEBUG (5, ("NIS Domain: %s\n", nis_domain));
2133 if (!strcmp (user_name, last_key))
2135 nis_result = last_value;
2136 nis_result_len = strlen (last_value);
2137 nis_error = 0;
2139 else
2141 if ((nis_error = yp_match (nis_domain, nis_map,
2142 user_name, strlen (user_name),
2143 &nis_result, &nis_result_len)) != 0)
2145 DEBUG (3, ("YP Error: \"%s\" while looking up \"%s\" in map \"%s\"\n",
2146 yperr_string (nis_error), user_name, nis_map));
2148 if (!nis_error && nis_result_len >= sizeof (pstring))
2150 nis_result_len = sizeof (pstring) - 1;
2152 fstrcpy (last_key, user_name);
2153 strncpy (last_value, nis_result, nis_result_len);
2154 last_value[nis_result_len] = '\0';
2157 strip_mount_options (&last_value);
2159 DEBUG (4, ("YP Lookup: %s resulted in %s\n", user_name, last_value));
2160 return last_value;
2162 #endif /* WITH_NISPLUS_HOME */
2163 #endif
2165 /*******************************************************************
2166 Patch from jkf@soton.ac.uk
2167 This is Luke's original function with the NIS lookup code
2168 moved out to a separate function.
2169 *******************************************************************/
2170 static char *
2171 automount_server (const char *user_name)
2173 static pstring server_name;
2174 (void) user_name;
2176 /* use the local machine name as the default */
2177 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2178 pstrcpy (server_name, local_machine);
2180 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2182 if (lp_nis_home_map ())
2184 int home_server_len;
2185 char *automount_value = automount_lookup (user_name);
2186 home_server_len = strcspn (automount_value, ":");
2187 DEBUG (5, ("NIS lookup succeeded. Home server length: %d\n", home_server_len));
2188 if (home_server_len > sizeof (pstring))
2190 home_server_len = sizeof (pstring);
2192 strncpy (server_name, automount_value, home_server_len);
2193 server_name[home_server_len] = '\0';
2195 #endif
2197 DEBUG (4, ("Home server: %s\n", server_name));
2199 return server_name;
2202 /*******************************************************************
2203 Patch from jkf@soton.ac.uk
2204 Added this to implement %p (NIS auto-map version of %H)
2205 *******************************************************************/
2206 static char *
2207 automount_path (char *user_name)
2209 static pstring server_path;
2211 /* use the passwd entry as the default */
2212 /* this will be the default if WITH_AUTOMOUNT is not used or fails */
2213 /* pstrcpy() copes with get_home_dir() returning NULL */
2214 pstrcpy (server_path, get_home_dir (user_name));
2216 #if (defined(HAVE_NETGROUP) && defined (WITH_AUTOMOUNT))
2218 if (lp_nis_home_map ())
2220 char *home_path_start;
2221 char *automount_value = automount_lookup (user_name);
2222 home_path_start = strchr (automount_value, ':');
2223 if (home_path_start != NULL)
2225 DEBUG (5, ("NIS lookup succeeded. Home path is: %s\n",
2226 home_path_start ? (home_path_start + 1) : ""));
2227 pstrcpy (server_path, home_path_start + 1);
2230 #endif
2232 DEBUG (4, ("Home server path: %s\n", server_path));
2234 return server_path;
2238 /*******************************************************************
2239 sub strings with useful parameters
2240 Rewritten by Stefaan A Eeckels <Stefaan.Eeckels@ecc.lu> and
2241 Paul Rippin <pr3245@nopc.eurostat.cec.be>
2242 ********************************************************************/
2243 void
2244 standard_sub_basic (char *str)
2246 char *s, *p;
2247 char pidstr[10];
2248 struct passwd *pass;
2249 const char *username = sam_logon_in_ssb ? samlogon_user : sesssetup_user;
2251 for (s = str; s && *s && (p = strchr (s, '%')); s = p)
2253 switch (*(p + 1))
2255 case 'G':
2257 if ((pass = Get_Pwnam (username)) != NULL)
2259 string_sub (p, "%G", gidtoname (pass->pw_gid));
2261 else
2263 p += 2;
2265 break;
2267 case 'N':
2268 string_sub (p, "%N", automount_server (username));
2269 break;
2270 case 'I':
2271 string_sub (p, "%I", client_addr (Client));
2272 break;
2273 case 'L':
2274 string_sub (p, "%L", local_machine);
2275 break;
2276 case 'M':
2277 string_sub (p, "%M", client_name (Client));
2278 break;
2279 case 'R':
2280 string_sub (p, "%R", remote_proto);
2281 break;
2282 case 'T':
2283 string_sub (p, "%T", timestring ());
2284 break;
2285 case 'U':
2286 string_sub (p, "%U", username);
2287 break;
2288 case 'a':
2289 string_sub (p, "%a", remote_arch);
2290 break;
2291 case 'd':
2293 slprintf (pidstr, sizeof (pidstr) - 1, "%d", (int) getpid ());
2294 string_sub (p, "%d", pidstr);
2295 break;
2297 case 'h':
2298 string_sub (p, "%h", myhostname);
2299 break;
2300 case 'm':
2301 string_sub (p, "%m", remote_machine);
2302 break;
2303 case 'v':
2304 string_sub (p, "%v", VERSION);
2305 break;
2306 case '$': /* Expand environment variables */
2308 /* Contributed by Branko Cibej <branko.cibej@hermes.si> */
2309 fstring envname;
2310 char *envval;
2311 char *q, *r;
2312 int copylen;
2314 if (*(p + 2) != '(')
2316 p += 2;
2317 break;
2319 if ((q = strchr (p, ')')) == NULL)
2321 DEBUG (0, ("standard_sub_basic: Unterminated environment \
2322 variable [%s]\n", p));
2323 p += 2;
2324 break;
2327 r = p + 3;
2328 copylen = MIN ((size_t) (q - r), (size_t) (sizeof (envname) - 1));
2329 strncpy (envname, r, copylen);
2330 envname[copylen] = '\0';
2332 if ((envval = getenv (envname)) == NULL)
2334 DEBUG (0, ("standard_sub_basic: Environment variable [%s] not set\n", envname));
2335 p += 2;
2336 break;
2339 copylen = MIN ((size_t) (q + 1 - p), (size_t) (sizeof (envname) - 1));
2340 strncpy (envname, p, copylen);
2341 envname[copylen] = '\0';
2342 string_sub (p, envname, envval);
2343 break;
2345 case '\0':
2346 p++;
2347 break; /* don't run off end if last character is % */
2348 default:
2349 p += 2;
2350 break;
2353 return;
2357 /****************************************************************************
2358 do some standard substitutions in a string
2359 ****************************************************************************/
2360 void
2361 standard_sub (connection_struct * conn, char *str)
2363 char *p, *s;
2364 const char *home;
2366 for (s = str; (p = strchr (s, '%')); s = p)
2368 switch (*(p + 1))
2370 case 'H':
2371 if ((home = get_home_dir (conn->user)))
2373 string_sub (p, "%H", home);
2375 else
2377 p += 2;
2379 break;
2381 case 'P':
2382 string_sub (p, "%P", conn->connectpath);
2383 break;
2385 case 'S':
2386 string_sub (p, "%S", lp_servicename (SNUM (conn)));
2387 break;
2389 case 'g':
2390 string_sub (p, "%g", gidtoname (conn->gid));
2391 break;
2392 case 'u':
2393 string_sub (p, "%u", conn->user);
2394 break;
2396 /* Patch from jkf@soton.ac.uk Left the %N (NIS
2397 * server name) in standard_sub_basic as it is
2398 * a feature for logon servers, hence uses the
2399 * username. The %p (NIS server path) code is
2400 * here as it is used instead of the default
2401 * "path =" string in [homes] and so needs the
2402 * service name, not the username. */
2403 case 'p':
2404 string_sub (p, "%p", automount_path (lp_servicename (SNUM (conn))));
2405 break;
2406 case '\0':
2407 p++;
2408 break; /* don't run off the end of the string
2411 default:
2412 p += 2;
2413 break;
2417 standard_sub_basic (str);
2422 /*******************************************************************
2423 are two IPs on the same subnet?
2424 ********************************************************************/
2425 BOOL
2426 same_net (struct in_addr ip1, struct in_addr ip2, struct in_addr mask)
2428 uint32 net1, net2, nmask;
2430 nmask = ntohl (mask.s_addr);
2431 net1 = ntohl (ip1.s_addr);
2432 net2 = ntohl (ip2.s_addr);
2434 return ((net1 & nmask) == (net2 & nmask));
2438 /****************************************************************************
2439 a wrapper for gethostbyname() that tries with all lower and all upper case
2440 if the initial name fails
2441 ****************************************************************************/
2442 struct hostent *
2443 Get_Hostbyname (const char *name)
2445 char *name2 = strdup (name);
2446 struct hostent *ret;
2448 if (!name2)
2450 DEBUG (0, ("Memory allocation error in Get_Hostbyname! panic\n"));
2451 exit (0);
2456 * This next test is redundent and causes some systems (with
2457 * broken isalnum() calls) problems.
2458 * JRA.
2461 #if 0
2462 if (!isalnum (*name2))
2464 free (name2);
2465 return (NULL);
2467 #endif /* 0 */
2469 ret = sys_gethostbyname (name2);
2470 if (ret != NULL)
2472 free (name2);
2473 return (ret);
2476 /* try with all lowercase */
2477 strlower (name2);
2478 ret = sys_gethostbyname (name2);
2479 if (ret != NULL)
2481 free (name2);
2482 return (ret);
2485 /* try with all uppercase */
2486 strupper (name2);
2487 ret = sys_gethostbyname (name2);
2488 if (ret != NULL)
2490 free (name2);
2491 return (ret);
2494 /* nothing works :-( */
2495 free (name2);
2496 return (NULL);
2499 #if 0
2500 /*******************************************************************
2501 turn a uid into a user name
2502 ********************************************************************/
2503 char *
2504 uidtoname (uid_t uid)
2506 static char name[40];
2507 struct passwd *pass = getpwuid (uid);
2508 if (pass)
2509 return (pass->pw_name);
2510 slprintf (name, sizeof (name) - 1, "%d", (int) uid);
2511 return (name);
2513 #endif /* 0 */
2515 /*******************************************************************
2516 turn a gid into a group name
2517 ********************************************************************/
2519 char *
2520 gidtoname (gid_t gid)
2522 static char name[40];
2523 struct group *grp = getgrgid (gid);
2524 if (grp)
2525 return (grp->gr_name);
2526 slprintf (name, sizeof (name) - 1, "%d", (int) gid);
2527 return (name);
2530 #if 0
2531 /*******************************************************************
2532 turn a user name into a uid
2533 ********************************************************************/
2534 uid_t
2535 nametouid (const char *name)
2537 struct passwd *pass = getpwnam (name);
2538 if (pass)
2539 return (pass->pw_uid);
2540 return (uid_t) - 1;
2542 #endif /* 0 */
2543 /*******************************************************************
2544 something really nasty happened - panic!
2545 ********************************************************************/
2546 void
2547 smb_panic (const char *why)
2549 const char *cmd = lp_panic_action ();
2550 if (cmd && *cmd)
2552 if (system (cmd))
2554 DEBUG (0, ("PANIC: cannot run panic handler command \"%s\"\n", cmd));
2557 DEBUG (0, ("PANIC: %s\n", why));
2558 dbgflush ();
2559 abort ();
2562 #if 0
2563 /*******************************************************************
2564 a readdir wrapper which just returns the file name
2565 ********************************************************************/
2566 char *
2567 readdirname (DIR * p)
2569 SMB_STRUCT_DIRENT *ptr;
2570 char *dname;
2572 if (!p)
2573 return (NULL);
2575 ptr = (SMB_STRUCT_DIRENT *) sys_readdir (p);
2576 if (!ptr)
2577 return (NULL);
2579 dname = ptr->d_name;
2581 #ifdef NEXT2
2582 if (telldir (p) < 0)
2583 return (NULL);
2584 #endif
2586 #ifdef HAVE_BROKEN_READDIR
2587 /* using /usr/ucb/cc is BAD */
2588 dname = dname - 2;
2589 #endif
2592 static pstring buf;
2593 memcpy (buf, dname, NAMLEN (ptr) + 1);
2594 dname = buf;
2597 return (dname);
2600 /*******************************************************************
2601 Utility function used to decide if the last component
2602 of a path matches a (possibly wildcarded) entry in a namelist.
2603 ********************************************************************/
2605 BOOL
2606 is_in_path (char *name, name_compare_entry * namelist)
2608 pstring last_component;
2609 char *p;
2611 DEBUG (8, ("is_in_path: %s\n", name));
2613 /* if we have no list it's obviously not in the path */
2614 if ((namelist == NULL) || ((namelist != NULL) && (namelist[0].name == NULL)))
2616 DEBUG (8, ("is_in_path: no name list.\n"));
2617 return False;
2620 /* Get the last component of the unix name. */
2621 p = strrchr (name, '/');
2622 strncpy (last_component, p ? ++p : name, sizeof (last_component) - 1);
2623 last_component[sizeof (last_component) - 1] = '\0';
2625 for (; namelist->name != NULL; namelist++)
2627 if (namelist->is_wild)
2630 * Look for a wildcard match. Use the old
2631 * 'unix style' mask match, rather than the
2632 * new NT one.
2634 if (unix_mask_match (last_component, namelist->name, case_sensitive, False))
2636 DEBUG (8, ("is_in_path: mask match succeeded\n"));
2637 return True;
2640 else
2642 if ((case_sensitive && (strcmp (last_component, namelist->name) == 0)) ||
2643 (!case_sensitive && (StrCaseCmp (last_component, namelist->name) == 0)))
2645 DEBUG (8, ("is_in_path: match succeeded\n"));
2646 return True;
2650 DEBUG (8, ("is_in_path: match not found\n"));
2652 return False;
2655 /*******************************************************************
2656 Strip a '/' separated list into an array of
2657 name_compare_enties structures suitable for
2658 passing to is_in_path(). We do this for
2659 speed so we can pre-parse all the names in the list
2660 and don't do it for each call to is_in_path().
2661 namelist is modified here and is assumed to be
2662 a copy owned by the caller.
2663 We also check if the entry contains a wildcard to
2664 remove a potentially expensive call to mask_match
2665 if possible.
2666 ********************************************************************/
2668 void
2669 set_namearray (name_compare_entry ** ppname_array, char *namelist)
2671 char *name_end;
2672 char *nameptr = namelist;
2673 int num_entries = 0;
2674 int i;
2676 (*ppname_array) = NULL;
2678 if ((nameptr == NULL) || ((nameptr != NULL) && (*nameptr == '\0')))
2679 return;
2681 /* We need to make two passes over the string. The
2682 first to count the number of elements, the second
2683 to split it.
2685 while (*nameptr)
2687 if (*nameptr == '/')
2689 /* cope with multiple (useless) /s) */
2690 nameptr++;
2691 continue;
2693 /* find the next / */
2694 name_end = strchr (nameptr, '/');
2696 /* oops - the last check for a / didn't find one. */
2697 if (name_end == NULL)
2698 break;
2700 /* next segment please */
2701 nameptr = name_end + 1;
2702 num_entries++;
2705 if (num_entries == 0)
2706 return;
2708 if (((*ppname_array) = (name_compare_entry *) malloc ((num_entries +
2709 1) * sizeof (name_compare_entry))) ==
2710 NULL)
2712 DEBUG (0, ("set_namearray: malloc fail\n"));
2713 return;
2716 /* Now copy out the names */
2717 nameptr = namelist;
2718 i = 0;
2719 while (*nameptr)
2721 if (*nameptr == '/')
2723 /* cope with multiple (useless) /s) */
2724 nameptr++;
2725 continue;
2727 /* find the next / */
2728 if ((name_end = strchr (nameptr, '/')) != NULL)
2730 *name_end = 0;
2733 /* oops - the last check for a / didn't find one. */
2734 if (name_end == NULL)
2735 break;
2737 (*ppname_array)[i].is_wild = ((strchr (nameptr, '?') != NULL) ||
2738 (strchr (nameptr, '*') != NULL));
2739 if (((*ppname_array)[i].name = strdup (nameptr)) == NULL)
2741 DEBUG (0, ("set_namearray: malloc fail (1)\n"));
2742 return;
2745 /* next segment please */
2746 nameptr = name_end + 1;
2747 i++;
2750 (*ppname_array)[i].name = NULL;
2752 return;
2755 /****************************************************************************
2756 routine to free a namearray.
2757 ****************************************************************************/
2759 void
2760 free_namearray (name_compare_entry * name_array)
2762 if (name_array == 0)
2763 return;
2765 if (name_array->name != NULL)
2766 free (name_array->name);
2768 free ((char *) name_array);
2772 /*******************************************************************
2773 is the name specified one of my netbios names
2774 returns true is it is equal, false otherwise
2775 ********************************************************************/
2776 BOOL
2777 is_myname (char *s)
2779 int n;
2780 BOOL ret = False;
2782 for (n = 0; my_netbios_names[n]; n++)
2784 if (strequal (my_netbios_names[n], s))
2785 ret = True;
2787 DEBUG (8, ("is_myname(\"%s\") returns %d\n", s, ret));
2788 return (ret);
2790 #endif /* 0 */
2791 #if 0 /* Can be useful one day */
2792 /*******************************************************************
2793 set the horrid remote_arch string based on an enum.
2794 ********************************************************************/
2795 void
2796 set_remote_arch (enum remote_arch_types type)
2798 ra_type = type;
2799 switch (type)
2801 case RA_WFWG:
2802 remote_arch = "WfWg";
2803 return;
2804 case RA_OS2:
2805 remote_arch = "OS2";
2806 return;
2807 case RA_WIN95:
2808 remote_arch = "Win95";
2809 return;
2810 case RA_WINNT:
2811 remote_arch = "WinNT";
2812 return;
2813 case RA_SAMBA:
2814 remote_arch = "Samba";
2815 return;
2816 default:
2817 ra_type = RA_UNKNOWN;
2818 remote_arch = "UNKNOWN";
2819 break;
2823 /*******************************************************************
2824 Get the remote_arch type.
2825 ********************************************************************/
2826 enum remote_arch_types
2827 get_remote_arch (void)
2829 return ra_type;
2831 #endif /* 0 */
2832 #if 0
2833 /*******************************************************************
2834 align a pointer to a multiple of 2 bytes
2835 ********************************************************************/
2836 char *
2837 align2 (char *q, char *base)
2839 if ((q - base) & 1)
2841 q++;
2843 return q;
2846 void
2847 out_ascii (FILE * f, unsigned char *buf, int len)
2849 int i;
2850 for (i = 0; i < len; i++)
2852 fprintf (f, "%c", isprint (buf[i]) ? buf[i] : '.');
2856 void
2857 out_data (FILE * f, char *buf1, int len, int per_line)
2859 unsigned char *buf = (unsigned char *) buf1;
2860 int i = 0;
2861 if (len <= 0)
2863 return;
2866 fprintf (f, "[%03X] ", i);
2867 for (i = 0; i < len;)
2869 fprintf (f, "%02X ", (int) buf[i]);
2870 i++;
2871 if (i % (per_line / 2) == 0)
2872 fprintf (f, " ");
2873 if (i % per_line == 0)
2875 out_ascii (f, &buf[i - per_line], per_line / 2);
2876 fprintf (f, " ");
2877 out_ascii (f, &buf[i - per_line / 2], per_line / 2);
2878 fprintf (f, "\n");
2879 if (i < len)
2880 fprintf (f, "[%03X] ", i);
2883 if ((i % per_line) != 0)
2885 int n;
2887 n = per_line - (i % per_line);
2888 fprintf (f, " ");
2889 if (n > (per_line / 2))
2890 fprintf (f, " ");
2891 while (n--)
2893 fprintf (f, " ");
2895 n = MIN (per_line / 2, i % per_line);
2896 out_ascii (f, &buf[i - (i % per_line)], n);
2897 fprintf (f, " ");
2898 n = (i % per_line) - n;
2899 if (n > 0)
2900 out_ascii (f, &buf[i - n], n);
2901 fprintf (f, "\n");
2904 #endif /* 0 */
2906 void
2907 print_asc (int level, unsigned char *buf, int len)
2909 int i;
2910 for (i = 0; i < len; i++)
2911 DEBUG (level, ("%c", isprint (buf[i]) ? buf[i] : '.'));
2914 void
2915 dump_data (int level, char *buf1, int len)
2917 unsigned char *buf = (unsigned char *) buf1;
2918 int i = 0;
2919 if (len <= 0)
2920 return;
2922 DEBUG (level, ("[%03X] ", i));
2923 for (i = 0; i < len;)
2925 DEBUG (level, ("%02X ", (int) buf[i]));
2926 i++;
2927 if (i % 8 == 0)
2928 DEBUG (level, (" "));
2929 if (i % 16 == 0)
2931 print_asc (level, &buf[i - 16], 8);
2932 DEBUG (level, (" "));
2933 print_asc (level, &buf[i - 8], 8);
2934 DEBUG (level, ("\n"));
2935 if (i < len)
2936 DEBUG (level, ("[%03X] ", i));
2939 if (i % 16)
2941 int n;
2943 n = 16 - (i % 16);
2944 DEBUG (level, (" "));
2945 if (n > 8)
2946 DEBUG (level, (" "));
2947 while (n--)
2948 DEBUG (level, (" "));
2950 n = MIN (8, i % 16);
2951 print_asc (level, &buf[i - (i % 16)], n);
2952 DEBUG (level, (" "));
2953 n = (i % 16) - n;
2954 if (n > 0)
2955 print_asc (level, &buf[i - n], n);
2956 DEBUG (level, ("\n"));
2960 #if 0
2961 /*****************************************************************************
2962 * Provide a checksum on a string
2964 * Input: s - the null-terminated character string for which the checksum
2965 * will be calculated.
2967 * Output: The checksum value calculated for s.
2969 * ****************************************************************************
2972 str_checksum (const char *s)
2974 int res = 0;
2975 int c;
2976 int i = 0;
2978 while (*s)
2980 c = *s;
2981 res ^= (c << (i % 15)) ^ (c >> (15 - (i % 15)));
2982 s++;
2983 i++;
2985 return (res);
2986 } /* str_checksum */
2989 /*****************************************************************
2990 zero a memory area then free it. Used to catch bugs faster
2991 *****************************************************************/
2992 void
2993 zero_free (void *p, size_t size)
2995 memset (p, 0, size);
2996 free (p);
2998 #endif /* 0 */