summaryrefslogtreecommitdiffstats
path: root/source4/scripting/python
Commit message (Collapse)AuthorAgeFilesLines
* s4:provision: place the sysvol share under "state dir" instead of "lock dir"Stefan Metzmacher2011-07-121-1/+1
| | | | metze
* s4:param: add "state dir" and "cache dir" optionsStefan Metzmacher2011-07-121-1/+9
| | | | metze
* dbcheck: use get_lDAPDisplayName_by_attid()Andrew Tridgell2011-07-111-11/+3
| | | | | | | this is better than doing a schema search inside the dbcheck code Autobuild-User: Andrew Tridgell <tridge@samba.org> Autobuild-Date: Mon Jul 11 07:43:18 CEST 2011 on sn-devel-104
* dsdb: added get_lDAPDisplayName_by_attidAndrew Tridgell2011-07-111-0/+4
| | | | | | | this allows conversion from a DRS attribute ID to a LDAP display name Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com> Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
* dbcheck: improved error checking in fixup of missing metdataAndrew Tridgell2011-07-111-26/+24
| | | | | | | | when fixing missing attributes in replPropertyMetaData, allow user to confirm changes, and check for exceptions Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org> Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* s4-provision: use samba.unix2nttime() instead of hard coding NTTIME offsetsAndrew Tridgell2011-07-111-2/+2
| | | | | Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org> Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* s4-samba-tool: dbcheck, check and fix broken metadataMatthieu Patou2011-07-111-0/+77
| | | | Signed-off-by: Andrew Tridgell <tridge@samba.org>
* s4-python: Add functions to get linkid and systemflags of an attributeMatthieu Patou2011-07-111-0/+8
| | | | Signed-off-by: Andrew Tridgell <tridge@samba.org>
* s4-provision: fix the value of creation timestamp to be a MS timestampMatthieu Patou2011-07-111-2/+2
| | | | Signed-off-by: Andrew Tridgell <tridge@samba.org>
* dbcheck: check all objects, including deleted objectsAndrew Tridgell2011-07-112-17/+18
| | | | | | | | | | this makes dbcheck search over all objects, deleted or not. This matters because when another DC replicates from this DC it replicates the deleted objects as well, so invalid attributes in deleted objects can cause problems on the new DC (for example, windows can get stuck or even crash during the replication) Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* dbcheck: added confirm_all support for remaining checksAndrew Tridgell2011-07-111-5/+10
| | | | | | | this allows the user to choose all/none for all the remaining database checks Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* dbcheck: use specified DB schema for non-LDAP URLsAndrew Tridgell2011-07-111-2/+9
| | | | | | | when connecting to a local database with -H we can use that databases schema Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* s4 provision: Add some of the AD-specific DNS records to the directoryKai Blin2011-07-072-8/+235
| | | | | | | Signed-off-by: Kai Blin <kai@samba.org> Autobuild-User: Kai Blin <kai@samba.org> Autobuild-Date: Thu Jul 7 02:29:53 CEST 2011 on sn-devel-104
* s4 provision: split up DNS provisioning into generic and samba-specific ldifsKai Blin2011-07-071-2/+10
| | | | Signed-off-by: Kai Blin <kai@samba.org>
* s4-dbcheck: support the 'none' option for promptsAndrew Tridgell2011-07-051-2/+10
| | | | | | | Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com> Autobuild-User: Andrew Tridgell <tridge@samba.org> Autobuild-Date: Tue Jul 5 08:22:40 CEST 2011 on sn-devel-104
* s4-pycommon: support 'none' as an option in confirmAndrew Tridgell2011-07-051-7/+20
| | | | | | this allows the user to ask for none of the changes of this type Pair-Programmed-With: Amitay Isaacs <amitay@gmail.com>
* dbcheck: only use a paged search when checking a ldap databaseAndrew Tridgell2011-07-051-1/+1
| | | | | paged searches don't work against a local database (they return only the first N objects)
* dbcheck: check for unknown attributes and offer to remove themAndrew Tridgell2011-07-051-3/+46
| | | | | | this asks the user if they want to remove an unknown attribute. You can also choose 'all' which will auto-confirm all questions about removing unknown attributes.
* s4-pycommon: allow an optional 'all' choice for confirm dialogsAndrew Tridgell2011-07-051-3/+9
| | | | | | when asking the user to confirm an action, allow for an 'all' choice, which will be used to allow the user to confirm all future requests of the same type
* s4:samba-tool: add "delegation" subcommands for S4U2Proxy and related stuffStefan Metzmacher2011-06-242-0/+269
| | | | | | | | | For now this only works on the local sam.ldb, but it shouldn't be hard to improve it to talk to remove servers. Pair-Programmed-With: Björn Baumbach <bb@sernet.de> metze
* s4:python/samba/samdb: add toggle_userAccountFlags() helper functionStefan Metzmacher2011-06-241-10/+35
| | | | | | | | And let enable_account() use it. Pair-Programmed-With: Björn Baumbach <bb@sernet.de> metze
* param: Remove remaining references to announce as and announce versionAndrew Bartlett2011-06-241-2/+0
|
* s4-dbcheck: fix uninitialized errstr in err_dn_target_mismatchMatthieu Patou2011-06-221-2/+3
| | | | | Autobuild-User: Matthieu Patou <mat@samba.org> Autobuild-Date: Wed Jun 22 21:22:27 CEST 2011 on sn-devel-104
* s4-dbcheck: remove unused includeMatthieu Patou2011-06-221-1/+1
|
* dbchecker: cope with a broken link to Deleted ObjectsAndrew Tridgell2011-06-221-2/+9
| | | | | if a DN link to Deleted Objects has a bad GUID, we need to use show_deleted
* dbchecker: fixed argument error for -H and DNAndrew Tridgell2011-06-221-1/+1
|
* dbchecker: when fixing a bad GUID in a DN, search by the string DNAndrew Tridgell2011-06-221-1/+1
|
* samba-tool: added --attrs option to dbcheckAndrew Tridgell2011-06-222-8/+15
| | | | this allows checking of a specific list of attributes
* samba-tool: make the dbcheck class available outside of samba-toolAndrew Tridgell2011-06-222-285/+324
| | | | | this will be used in provision, and probably in upgradeprovision as well
* samba-tool: added --quiet option to dbcheckAndrew Tridgell2011-06-221-35/+43
| | | | | this will be used to allow for other tools (such as provision) to call into dbcheck without generating a lot of noise
* samba-tool: allow for running dbcheck against a remove ldap serverAndrew Tridgell2011-06-221-5/+14
| | | | this is useful for running it against a Windows server
* samba-tool: expanded dbcheck DN checkingAndrew Tridgell2011-06-221-21/+104
| | | | | | | this now checks for bad GUID elements in DN links, and offers to fix them when possible Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
* samba-tool: added missing GUID component checks to dbcheckAndrew Tridgell2011-06-221-4/+93
| | | | | | | Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org> Autobuild-User: Andrew Tridgell <tridge@samba.org> Autobuild-Date: Wed Jun 22 07:59:30 CEST 2011 on sn-devel-104
* pydsdb: added get_syntax_oid_from_lDAPDisplayName()Andrew Tridgell2011-06-221-0/+5
| | | | | | this gives you access to the syntax oid of an attribute Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
* samba-tool: try to keep dbcheck.py in a logical orderingAndrew Tridgell2011-06-221-29/+38
| | | | keep individual error handlers together and separate from driver code
* tdb2: create tdb2 versions of various testing TDBs.Rusty Russell2011-06-201-2/+5
| | | | | | | Soon, TDB2 will handle tdb1 files, but until then, we substitute. Signed-off-by: Rusty Russell <rusty@rustcorp.com.au>
* s4-sambatool: extract the confirm function in a separte module for reuseMatthieu Patou2011-06-192-10/+36
|
* s4-samba-tool: remove unused importsMatthieu Patou2011-06-191-2/+1
|
* s4-samba-tool: use correct object notation ie. obj.method rather than ↵Matthieu Patou2011-06-191-37/+31
| | | | method(obj, ...)
* s4-sambatool: use correct way to call class methodsMatthieu Patou2011-06-191-53/+54
|
* s4-upgradeprovision: improve message outputMatthieu Patou2011-06-191-1/+1
|
* s4-provision: Remove hard coded SD for CN=Sites containerMatthieu Patou2011-06-191-15/+0
| | | | | | | | With the fix introduced by Nadya in changeset 622ef6aed82a2f2f7748c2a88535486af77487de we are now able to generate correct SD (at least the same as W2k3R2 with a Forest Level of 2003), so there is no need for this fix anymore as it makes SDs for Forest Level 2003 and lower incorrect.
* s4-upgradeprovision: handle the fact that oEMInformation might not be presentMatthieu Patou2011-06-191-2/+5
|
* s4-python: make checks of sacl in get_diff_sddls optionnalMatthieu Patou2011-06-191-2/+6
|
* s4-upgradeprovision: introduce invocation id in lastprovisionUSNsMatthieu Patou2011-06-191-17/+39
|
* s4-python: fix wrong discovery of the site name in find_key_provision_parametersMatthieu Patou2011-06-191-1/+1
|
* s4-upgradeprovisision: fix bug 8063, old SD can miss some componenent ↵Matthieu Patou2011-06-191-16/+20
| | | | | | | | | (group, owner, ...) Don't make the assumption that SD are correct, they can be wrong and misformed. Fix this bug: https://bugzilla.samba.org/show_bug.cgi?id=8063
* samba-tool: exit with non-zero status on dbcheck failureAndrew Tridgell2011-06-171-1/+3
| | | | Pair-Programmed-With: Andrew Bartlett <abartlet@samba.org>
* samba-tool: show success message on group operationsAndrew Tridgell2011-06-171-0/+4
|
* s4-pysamdb: fixed the normalisation of grouptype in group addAndrew Tridgell2011-06-171-1/+7
| | | | | | | ldap integers are signed Autobuild-User: Andrew Tridgell <tridge@samba.org> Autobuild-Date: Fri Jun 17 05:43:18 CEST 2011 on sn-devel-104
n> * The filename restriction is a cheat so that we can use buf[] to store * assorted temporary goo. * * Examples, assuming style 0 failed. * * suffix = ".bak" (style 1) * foo.bar => foo.bak * foo.bak => foo.$$$ (fallback) * foo.$$$ => foo.~~~ (fallback) * makefile => makefile.bak * * suffix = "~" (style 2) * foo.c => foo.c~ * foo.c~ => foo.c~~ * foo.c~~ => foo~.c~~ * foo~.c~~ => foo~~.c~~ * foo~~~~~.c~~ => foo~~~~~.$$$ (fallback) * * foo.pas => foo~.pas * makefile => makefile.~ * longname.fil => longname.fi~ * longname.fi~ => longnam~.fi~ * longnam~.fi~ => longnam~.$$$ * */ static int valid_filename(char *s); static char suffix1[] = ".$$$"; static char suffix2[] = ".~~~"; #define ext (&buf[1000]) #define strEQ(s1,s2) (strcmp(s1,s2) == 0) void ruby_add_suffix(str, suffix) VALUE str; char *suffix; { int baselen; int extlen = strlen(suffix); char *s, *t, *p; long slen; char buf[1024]; if (RSTRING(str)->len > 1000) rb_fatal("Cannot do inplace edit on long filename (%ld characters)", RSTRING(str)->len); #if defined(DJGPP) || defined(__CYGWIN32__) || defined(_WIN32) /* Style 0 */ slen = RSTRING(str)->len; rb_str_cat(str, suffix, extlen); #if defined(DJGPP) if (_USE_LFN) return; #else if (valid_filename(RSTRING(str)->ptr)) return; #endif /* Fooey, style 0 failed. Fix str before continuing. */ RSTRING(str)->ptr[RSTRING(str)->len = slen] = '\0'; #endif slen = extlen; t = buf; baselen = 0; s = RSTRING(str)->ptr; while ((*t = *s) && *s != '.') { baselen++; if (*s == '\\' || *s == '/') baselen = 0; s++; t++; } p = t; t = ext; extlen = 0; while (*t++ = *s++) extlen++; if (extlen == 0) { ext[0] = '.'; ext[1] = 0; extlen++; } if (*suffix == '.') { /* Style 1 */ if (strEQ(ext, suffix)) goto fallback; strcpy(p, suffix); } else if (suffix[1] == '\0') { /* Style 2 */ if (extlen < 4) { ext[extlen] = *suffix; ext[++extlen] = '\0'; } else if (baselen < 8) { *p++ = *suffix; } else if (ext[3] != *suffix) { ext[3] = *suffix; } else if (buf[7] != *suffix) { buf[7] = *suffix; } else goto fallback; strcpy(p, ext); } else { /* Style 3: Panic */ fallback: (void)memcpy(p, strEQ(ext, suffix1) ? suffix2 : suffix1, 5); } rb_str_resize(str, strlen(buf)); memcpy(RSTRING(str)->ptr, buf, RSTRING(str)->len); } #if defined(__CYGWIN32__) || defined(_WIN32) static int valid_filename(char *s) { int fd; /* // if the file exists, then it's a valid filename! */ if (_access(s, 0) == 0) { return 1; } /* // It doesn't exist, so see if we can open it. */ if ((fd = _open(s, O_CREAT, 0666)) >= 0) { _close(fd); _unlink(s); /* don't leave it laying around */ return 1; } return 0; } #endif #endif #if defined __DJGPP__ #include <dpmi.h> static char dbcs_table[256]; int make_dbcs_table() { __dpmi_regs r; struct { unsigned char start; unsigned char end; } vec; int offset; memset(&r, 0, sizeof(r)); r.x.ax = 0x6300; __dpmi_int(0x21, &r); offset = r.x.ds * 16 + r.x.si; for (;;) { int i; dosmemget(offset, sizeof vec, &vec); if (!vec.start && !vec.end) break; for (i = vec.start; i <= vec.end; i++) dbcs_table[i] = 1; offset += 2; } } int mblen(const char *s, size_t n) { static int need_init = 1; if (need_init) { make_dbcs_table(); need_init = 0; } if (s) { if (n == 0 || *s == 0) return 0; else if (!s[1]) return 1; return dbcs_table[(unsigned char)*s] + 1; } else return 1; } struct PathList { struct PathList *next; char *path; }; struct PathInfo { struct PathList *head; int count; }; static void push_element(const char *path, VALUE vinfo) { struct PathList *p; struct PathInfo *info = (struct PathInfo *)vinfo; p = ALLOC(struct PathList); MEMZERO(p, struct PathList, 1); p->path = ruby_strdup(path); p->next = info->head; info->head = p; info->count++; } #include <dirent.h> int __opendir_flags = __OPENDIR_PRESERVE_CASE; char ** __crt0_glob_function(char *path) { int len = strlen(path); int i; char **rv; char path_buffer[PATH_MAX]; char *buf = path_buffer; char *p; struct PathInfo info; struct PathList *plist; if (PATH_MAX <= len) buf = ruby_xmalloc(len + 1); strncpy(buf, path, len); buf[len] = '\0'; for (p = buf; *p; p += mblen(p, RUBY_MBCHAR_MAXSIZE)) if (*p == '\\') *p = '/'; info.count = 0; info.head = 0; rb_glob(buf, push_element, (VALUE)&info); if (buf != path_buffer) ruby_xfree(buf); if (info.count == 0) return 0; rv = ruby_xmalloc((info.count + 1) * sizeof (char *)); plist = info.head; i = 0; while (plist) { struct PathList *cur; rv[i] = plist->path; cur = plist; plist = plist->next; ruby_xfree(cur); i++; } rv[i] = 0; return rv; } #endif /* mm.c */ #define A ((int*)a) #define B ((int*)b) #define C ((int*)c) #define D ((int*)d) #define mmprepare(base, size) do {\ if (((long)base & (0x3)) == 0)\ if (size >= 16) mmkind = 1;\ else mmkind = 0;\ else mmkind = -1;\ high = (size & (~0xf));\ low = (size & 0x0c);\ } while (0)\ #define mmarg mmkind, size, high, low static void mmswap_(a, b, mmarg) register char *a, *b; int mmarg; { register int s; if (a == b) return; if (mmkind >= 0) { if (mmkind > 0) { register char *t = a + high; do { s = A[0]; A[0] = B[0]; B[0] = s; s = A[1]; A[1] = B[1]; B[1] = s; s = A[2]; A[2] = B[2]; B[2] = s; s = A[3]; A[3] = B[3]; B[3] = s; a += 16; b += 16; } while (a < t); } if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = s; if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = s; if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = s;}}} } else { register char *t = a + size; do {s = *a; *a++ = *b; *b++ = s;} while (a < t); } } #define mmswap(a,b) mmswap_((a),(b),mmarg) static void mmrot3_(a, b, c, mmarg) register char *a, *b, *c; int mmarg; { register int s; if (mmkind >= 0) { if (mmkind > 0) { register char *t = a + high; do { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s; s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s; s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s; s = A[3]; A[3] = B[3]; B[3] = C[3]; C[3] = s; a += 16; b += 16; c += 16; } while (a < t); } if (low != 0) { s = A[0]; A[0] = B[0]; B[0] = C[0]; C[0] = s; if (low >= 8) { s = A[1]; A[1] = B[1]; B[1] = C[1]; C[1] = s; if (low == 12) {s = A[2]; A[2] = B[2]; B[2] = C[2]; C[2] = s;}}} } else { register char *t = a + size; do {s = *a; *a++ = *b; *b++ = *c; *c++ = s;} while (a < t); } } #define mmrot3(a,b,c) mmrot3_((a),(b),(c),mmarg) /* qs6.c */ /*****************************************************/ /* */ /* qs6 (Quick sort function) */ /* */ /* by Tomoyuki Kawamura 1995.4.21 */ /* kawamura@tokuyama.ac.jp */ /*****************************************************/ typedef struct { char *LL, *RR; } stack_node; /* Stack structure for L,l,R,r */ #define PUSH(ll,rr) do { top->LL = (ll); top->RR = (rr); ++top; } while (0) /* Push L,l,R,r */ #define POP(ll,rr) do { --top; ll = top->LL; rr = top->RR; } while (0) /* Pop L,l,R,r */ #define med3(a,b,c) ((*cmp)(a,b,d)<0 ? \ ((*cmp)(b,c,d)<0 ? b : ((*cmp)(a,c,d)<0 ? c : a)) : \ ((*cmp)(b,c,d)>0 ? b : ((*cmp)(a,c,d)<0 ? a : c))) void ruby_qsort (base, nel, size, cmp, d) void* base; const int nel; const int size; int (*cmp)(); void *d; { register char *l, *r, *m; /* l,r:left,right group m:median point */ register int t, eq_l, eq_r; /* eq_l: all items in left group are equal to S */ char *L = base; /* left end of curren region */ char *R = (char*)base + size*(nel-1); /* right end of current region */ int chklim = 63; /* threshold of ordering element check */ stack_node stack[32], *top = stack; /* 32 is enough for 32bit CPU */ int mmkind, high, low; if (nel <= 1) return; /* need not to sort */ mmprepare(base, size); goto start; nxt: if (stack == top) return; /* return if stack is empty */ POP(L,R); for (;;) { start: if (L + size == R) { /* 2 elements */ if ((*cmp)(L,R,d) > 0) mmswap(L,R); goto nxt; } l = L; r = R; t = (r - l + size) / size; /* number of elements */ m = l + size * (t >> 1); /* calculate median value */ if (t >= 60) { register char *m1; register char *m3; if (t >= 200) { t = size*(t>>3); /* number of bytes in splitting 8 */ { register char *p1 = l + t; register char *p2 = p1 + t; register char *p3 = p2 + t; m1 = med3(p1, p2, p3); p1 = m + t; p2 = p1 + t; p3 = p2 + t; m3 = med3(p1, p2, p3); } } else { t = size*(t>>2); /* number of bytes in splitting 4 */ m1 = l + t; m3 = m + t; } m = med3(m1, m, m3); } if ((t = (*cmp)(l,m,d)) < 0) { /*3-5-?*/ if ((t = (*cmp)(m,r,d)) < 0) { /*3-5-7*/ if (chklim && nel >= chklim) { /* check if already ascending order */ char *p; chklim = 0; for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) > 0) goto fail; goto nxt; } fail: goto loopA; /*3-5-7*/ } if (t > 0) { if ((*cmp)(l,r,d) <= 0) {mmswap(m,r); goto loopA;} /*3-5-4*/ mmrot3(r,m,l); goto loopA; /*3-5-2*/ } goto loopB; /*3-5-5*/ } if (t > 0) { /*7-5-?*/ if ((t = (*cmp)(m,r,d)) > 0) { /*7-5-3*/ if (chklim && nel >= chklim) { /* check if already ascending order */ char *p; chklim = 0; for (p=l; p<r; p+=size) if ((*cmp)(p,p+size,d) < 0) goto fail2; while (l<r) {mmswap(l,r); l+=size; r-=size;} /* reverse region */ goto nxt; } fail2: mmswap(l,r); goto loopA; /*7-5-3*/ } if (t < 0) { if ((*cmp)(l,r,d) <= 0) {mmswap(l,m); goto loopB;} /*7-5-8*/ mmrot3(l,m,r); goto loopA; /*7-5-6*/ } mmswap(l,r); goto loopA; /*7-5-5*/ } if ((t = (*cmp)(m,r,d)) < 0) {goto loopA;} /*5-5-7*/ if (t > 0) {mmswap(l,r); goto loopB;} /*5-5-3*/ /* determining splitting type in case 5-5-5 */ /*5-5-5*/ for (;;) { if ((l += size) == r) goto nxt; /*5-5-5*/ if (l == m) continue; if ((t = (*cmp)(l,m,d)) > 0) {mmswap(l,r); l = L; goto loopA;}/*575-5*/ if (t < 0) {mmswap(L,l); l = L; goto loopB;} /*535-5*/ } loopA: eq_l = 1; eq_r = 1; /* splitting type A */ /* left <= median < right */ for (;;) { for (;;) { if ((l += size) == r) {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} if (l == m) continue; if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} if (t < 0) eq_l = 0; } for (;;) { if (l == (r -= size)) {l -= size; if (l != m) mmswap(m,l); l -= size; goto fin;} if (r == m) {m = l; break;} if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} if (t == 0) break; } mmswap(l,r); /* swap left and right */ } loopB: eq_l = 1; eq_r = 1; /* splitting type B */ /* left < median <= right */ for (;;) { for (;;) { if (l == (r -= size)) {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} if (r == m) continue; if ((t = (*cmp)(r,m,d)) < 0) {eq_l = 0; break;} if (t > 0) eq_r = 0; } for (;;) { if ((l += size) == r) {r += size; if (r != m) mmswap(r,m); r += size; goto fin;} if (l == m) {m = r; break;} if ((t = (*cmp)(l,m,d)) > 0) {eq_r = 0; break;} if (t == 0) break; } mmswap(l,r); /* swap left and right */ } fin: if (eq_l == 0) /* need to sort left side */ if (eq_r == 0) /* need to sort right side */ if (l-L < R-r) {PUSH(r,R); R = l;} /* sort left side first */ else {PUSH(L,l); L = r;} /* sort right side first */ else R = l; /* need to sort left side only */ else if (eq_r == 0) L = r; /* need to sort right side only */ else goto nxt; /* need not to sort both sides */ } } char * ruby_strdup(str) const char *str; { char *tmp; int len = strlen(str) + 1; tmp = xmalloc(len); memcpy(tmp, str, len); return tmp; } char * ruby_getcwd() { #ifdef HAVE_GETCWD int size = 200; char *buf = xmalloc(size); while (!getcwd(buf, size)) { if (errno != ERANGE) { free(buf); rb_sys_fail("getcwd"); } size *= 2; buf = xrealloc(buf, size); } #else # ifndef PATH_MAX # define PATH_MAX 8192 # endif char *buf = xmalloc(PATH_MAX+1); if (!getwd(buf)) { free(buf); rb_sys_fail("getwd"); } #endif return buf; } /* copyright notice for strtod implementation -- * * Copyright (c) 1988-1993 The Regents of the University of California. * Copyright (c) 1994 Sun Microsystems, Inc. * * Permission to use, copy, modify, and distribute this * software and its documentation for any purpose and without * fee is hereby granted, provided that the above copyright * notice appear in all copies. The University of California * makes no representations about the suitability of this * software for any purpose. It is provided "as is" without * express or implied warranty. * */ #define TRUE 1 #define FALSE 0 static int MDMINEXPT = -323; static int MDMAXEXPT = 309; static double powersOf10[] = { /* Table giving binary powers of 10. Entry */ 10.0, /* is 10^2^i. Used to convert decimal */ 100.0, /* exponents into floating-point numbers. */ 1.0e4, 1.0e8, 1.0e16, 1.0e32, 1.0e64, 1.0e128, 1.0e256 }; /* *---------------------------------------------------------------------- * * strtod -- * * This procedure converts a floating-point number from an ASCII * decimal representation to internal double-precision format. * * Results: * The return value is the double-precision floating-point * representation of the characters in string. If endPtr isn't * NULL, then *endPtr is filled in with the address of the * next character after the last one that was part of the * floating-point number. * * Side effects: * None. * *---------------------------------------------------------------------- */ double ruby_strtod(string, endPtr) const char *string; /* A decimal ASCII floating-point number, * optionally preceded by white space. * Must have form "-I.FE-X", where I is the * integer part of the mantissa, F is the * fractional part of the mantissa, and X * is the exponent. Either of the signs * may be "+", "-", or omitted. Either I * or F may be omitted, but both cannot be * ommitted at once. The decimal * point isn't necessary unless F is present. * The "E" may actually be an "e". E and X * may both be omitted (but not just one). */ char **endPtr; /* If non-NULL, store terminating character's * address here. */ { int sign, expSign = FALSE; double fraction, dblExp, *d; register const char *p; register int c; int exp = 0; /* Exponent read from "EX" field. */ int fracExp = 0; /* Exponent that derives from the fractional * part. Under normal circumstatnces, it is * the negative of the number of digits in F. * However, if I is very long, the last digits * of I get dropped (otherwise a long I with a * large negative exponent could cause an * unnecessary overflow on I alone). In this * case, fracExp is incremented one for each * dropped digit. */ int mantSize = 0; /* Number of digits in mantissa. */ int hasPoint = FALSE; /* Decimal point exists. */ int hasDigit = FALSE; /* I or F exists. */ const char *pMant; /* Temporarily holds location of mantissa * in string. */ const char *pExp; /* Temporarily holds location of exponent * in string. */ /* * Strip off leading blanks and check for a sign. */ errno = 0; p = string; while (ISSPACE(*p)) { p += 1; } if (*p == '-') { sign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } sign = FALSE; } /* * Count the number of digits in the mantissa * and also locate the decimal point. */ for ( ; c = *p; p += 1) { if (!ISDIGIT(c)) { if (c != '.' || hasPoint) { break; } hasPoint = TRUE; } else { if (hasPoint) { /* already in fractional part */ fracExp -= 1; } if (mantSize) { /* already in mantissa */ mantSize += 1; } else if (c != '0') { /* have entered mantissa */ mantSize += 1; pMant = p; } hasDigit = TRUE; } } /* * Now suck up the digits in the mantissa. Use two integers to * collect 9 digits each (this is faster than using floating-point). * If the mantissa has more than 18 digits, ignore the extras, since * they can't affect the value anyway. */ pExp = p; if (mantSize) { p = pMant; } if (mantSize > 18) { fracExp += (mantSize - 18); mantSize = 18; } if (!hasDigit) { fraction = 0.0; p = string; } else { int frac1, frac2; frac1 = 0; for ( ; mantSize > 9; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac1 = 10*frac1 + (c - '0'); } frac2 = 0; for (; mantSize > 0; mantSize -= 1) { c = *p; p += 1; if (c == '.') { c = *p; p += 1; } frac2 = 10*frac2 + (c - '0'); } /* * Skim off the exponent. */ p = pExp; if ((*p == 'E') || (*p == 'e')) { p += 1; if (*p == '-') { expSign = TRUE; p += 1; } else { if (*p == '+') { p += 1; } expSign = FALSE; } while (ISDIGIT(*p)) { exp = exp * 10 + (*p - '0'); p += 1; } } if (expSign) { exp = fracExp - exp; } else { exp = fracExp + exp; } /* * Generate a floating-point number that represents the exponent. * Do this by processing the exponent one bit at a time to combine * many powers of 2 of 10. Then combine the exponent with the * fraction. */ if (exp >= MDMAXEXPT - 18) { exp = MDMAXEXPT; errno = ERANGE; } else if (exp < MDMINEXPT + 18) { exp = MDMINEXPT; errno = ERANGE; } fracExp = exp; exp += 9; if (exp < 0) { expSign = TRUE; exp = -exp; } else { expSign = FALSE; } dblExp = 1.0; for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { if (exp & 01) { dblExp *= *d; } } if (expSign) { fraction = frac1 / dblExp; } else { fraction = frac1 * dblExp; } exp = fracExp; if (exp < 0) { expSign = TRUE; exp = -exp; } else { expSign = FALSE; } dblExp = 1.0; for (d = powersOf10; exp != 0; exp >>= 1, d += 1) { if (exp & 01) { dblExp *= *d; } } if (expSign) { fraction += frac2 / dblExp; } else { fraction += frac2 * dblExp; } } if (endPtr != NULL) { *endPtr = (char *) p; } if (sign) { return -fraction; } return fraction; }