uint16 _api_DosNetServerGetInfo(PCONN_HND phnd, io_struct * ps, uint16 sLevel, RCVBUF pbBuffer, RCVBUFLEN cbBuffer, uint16 *pcTotalAvail) { SERVER_INFO_1 sv1; DEBUG(10,("DosNetServerGetInfo: %d buf %d\n", sLevel, cbBuffer)); StrnCpy(sv1.sv1_name, local_machine, 16); strupper(sv1.sv1_name); sv1.sv1_version_major = 4; sv1.sv1_version_minor = 1; sv1.sv1_type = SV_TYPE_NT; sv1.sv1_comment_or_master_browser = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); switch (sLevel) { case 1: { if (!io_SERVER_INFO_1("sv1", ps, 0, &sv1, PARSE_SCALARS)) return NERR_BufTooSmall; if (!io_SERVER_INFO_1("sv1", ps, 0, &sv1, PARSE_OFFSETS)) return NERR_BufTooSmall; return ERRsuccess; } } return ERRunknownlevel; }
void file_dirscan( char *dir, scanback func, void *closure ) { PATHNAME f; string filespec[1]; long handle; int ret; struct _find_t finfo[1]; /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); dir = *dir ? dir : "."; /* Special case \ or d:\ : enter it */ string_copy( filespec, dir ); if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '\\' ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); else if( f.f_dir.len == 3 && f.f_dir.ptr[1] == ':' ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); else string_push_back( filespec, '/' ); string_push_back( filespec, '*' ); /* Now enter contents of directory */ if( DEBUG_BINDSCAN ) printf( "scan directory %s\n", filespec->value ); /* Time info in dos find_t is not very useful. It consists */ /* of a separate date and time, and putting them together is */ /* not easy. So we leave that to a later stat() call. */ if( !_dos_findfirst( filespec->value, _A_NORMAL|_A_RDONLY|_A_SUBDIR, finfo ) ) { string filename[1]; string_new( filename ); do { f.f_base.ptr = finfo->name; f.f_base.len = strlen( finfo->name ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 ); } while( !_dos_findnext( finfo ) ); string_free( filename ); } }
void announce_remote(time_t t) { char *s; const char *ptr; static time_t last_time = 0; pstring s2; struct in_addr addr; char *comment; int stype = lp_default_server_announce(); if (last_time && (t < (last_time + REMOTE_ANNOUNCE_INTERVAL))) return; last_time = t; s = lp_remote_announce(); if (!*s) return; comment = string_truncate(lp_serverstring(), MAX_SERVER_STRING_LENGTH); for (ptr=s; next_token(&ptr,s2,NULL,sizeof(s2)); ) { /* The entries are of the form a.b.c.d/WORKGROUP with WORKGROUP being optional */ const char *wgroup; char *pwgroup; int i; pwgroup = strchr_m(s2,'/'); if (pwgroup) *pwgroup++ = 0; if (!pwgroup || !*pwgroup) wgroup = lp_workgroup(); else wgroup = pwgroup; addr = *interpret_addr2(s2); /* Announce all our names including aliases */ /* Give the ip address as the address of our first broadcast subnet. */ for(i=0; my_netbios_names(i); i++) { const char *name = my_netbios_names(i); DEBUG(5,("announce_remote: Doing remote announce for server %s to IP %s.\n", name, inet_ntoa(addr) )); send_announcement(FIRST_SUBNET, ANN_HostAnnouncement, name, /* From nbt name. */ wgroup, 0x1d, /* To nbt name. */ addr, /* To ip. */ REMOTE_ANNOUNCE_INTERVAL, /* Time until next announce. */ name, /* Name to announce. */ stype, /* Type field. */ comment); } } }
/* EN: Enter Newline */ void cmd_en (int argc, char *argv[]) { pad_t *pad = e->cpad; int xpos; int ypos; line_t *cline; line_t *newline; char *extratext; int intab; if (!(e->cpad->flags & FILE_WRITE)) { output_message_c ("en", "Pad is read-only."); return; } ypos = pad->curs_y + pad->offset_y; if (ypos > pad->line_count) pad_grow (pad, ypos); LINE_insert (pad, ypos, ""); cline = LINE_get_line_at (pad, ypos); if (cline->str != NULL) { xpos = get_string_pos (pad->curs_x + pad->offset_x, cline->str->data, &intab); if ((size_t)xpos < strlen (cline->str->data)) { /* We're 'inside' the string. Get the text on the * right, and truncate the current string. Then put * the 'extra' text on the line we've inserted or * allocated. */ extratext = cline->str->data + xpos; newline = LINE_get_line_at (pad, ypos + 1); newline->str = string_alloc ("%s", extratext); string_truncate (cline->str, xpos); } } pad->curs_x = 1; pad->offset_x = 0; if (pad->curs_y == pad->height) { pad->offset_y++; } else { pad->curs_y++; } if (e->occupied_window == COMMAND_WINDOW) e->occupied_window = COMMAND_WINDOW_EXECUTE; else pad_modified (pad); }
int file_collect_dir_content_( file_info_t * const d ) { LIST * files = L0; PATHNAME f; int n; STRUCT_DIRENT ** namelist; STRUCT_DIRENT * dirent; string path[ 1 ]; char const * dirstr; assert( d ); assert( d->is_dir ); assert( list_empty( d->files ) ); dirstr = object_str( d->name ); memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dirstr; f.f_dir.len = strlen( dirstr ); if ( !*dirstr ) dirstr = "."; if ( -1 == ( n = scandir( dirstr, &namelist, NULL, alphasort ) ) ) return -1; string_new( path ); while ( n-- ) { OBJECT * name; dirent = namelist[ n ]; f.f_base.ptr = dirent->d_name #ifdef old_sinix - 2 /* Broken structure definition on sinix. */ #endif ; f.f_base.len = strlen( f.f_base.ptr ); string_truncate( path, 0 ); path_build( &f, path ); name = object_new( path->value ); /* Immediately stat the file to preserve invariants. */ if ( file_query( name ) ) files = list_push_back( files, name ); else object_free( name ); free( dirent ); } string_free( path ); free( namelist ); d->files = files; return 0; }
void file_dirscan( char *dir, scanback func, void *closure ) { PATHNAME f; DIR *d; STRUCT_DIRENT *dirent; string filename[1]; /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); dir = *dir ? dir : "."; /* Special case / : enter it */ if( f.f_dir.len == 1 && f.f_dir.ptr[0] == '/' ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); /* Now enter contents of directory */ if( !( d = opendir( dir ) ) ) return; if( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir ); string_new( filename ); while( dirent = readdir( d ) ) { # ifdef old_sinix /* Broken structure definition on sinix. */ f.f_base.ptr = dirent->d_name - 2; # else f.f_base.ptr = dirent->d_name; # endif f.f_base.len = strlen( f.f_base.ptr ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 ); } string_free( filename ); closedir( d ); }
static void StrAppend(char *buffer, char *fmt, int len, char *str) { char OneItem[100]; char msg[100]; sprintf(OneItem,fmt, str); string_truncate(OneItem, msg, len, 100); if((int)strlen(OneItem) > len) { css_warning("%s truncated to (%s) to fit format requirements...\n", OneItem, msg); } strncat(buffer, msg, len); strcat(buffer, " "); }
void mangle_map(pstring OutName, BOOL need83, BOOL cache83, int snum) { /* name mangling can be disabled for speed, in which case we just truncate the string */ if (!lp_manglednames(snum)) { if (need83) { string_truncate(OutName, 12); } return; } /* invoke the inane "mangled map" code */ mangle_map_filename(OutName, snum); mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(snum)); }
void mangle_map(pstring OutName, BOOL need83, BOOL cache83, const struct share_params *p) { /* name mangling can be disabled for speed, in which case we just truncate the string */ if (!lp_manglednames(p)) { if (need83) { string_truncate(OutName, 12); } return; } /* invoke the inane "mangled map" code */ mangle_map_filename(OutName, p); mangle_fns->name_map(OutName, need83, cache83, lp_defaultcase(p->service), p); }
VOID setting_write(CHAR *filename, CHAR *key, CHAR *value) { STRING *str; CHAR *tmpbuf; CHAR *pkey; CHAR *p; os_lock_lock(settinglock); tmpbuf = setting_load_file(filename); str = string_new(tmpbuf); pkey = setting_find_key(tmpbuf, key, NULL); if(pkey != NULL) { string_truncate(str, pkey - tmpbuf); str = string_append(str, key); str = string_append(str, "="); str = string_append(str, value); str = string_append(str, "\r\n"); p = strstr(pkey, "\n"); if(p) str = string_append(str, p + 2); else str = string_append(str, "\n\n"); } else { str = string_append(str, key); str = string_append(str, "="); str = string_append(str, value); str = string_append(str, "\r\n"); } os_free(tmpbuf); setting_save_file(filename, str->str); string_free(str); os_lock_unlock(settinglock); }
buffer_t *buffer_load (char *file_name) { char *full_path; char line[512]; FILE *f; buffer_t *buf; /* use line first to store the full path name */ full_path = line; if (*file_name != '/') sprintf (full_path, "%s/.gronda/buffer/%s", getenv ("HOME"), file_name); else strcpy (full_path, file_name); f = fopen (full_path, "r"); if (f == NULL) { output_message ("Error loading buffer %s", file_name); return NULL; } buf = buffer_create (file_name); if (buf == NULL) { output_message ("Error creating buffer"); return NULL; } if (*(buf->str->data)) string_truncate (buf->str, 0); /* line is now used to store data from the file stream */ while (fgets (line, 512, f)) string_append (buf->str, line); fclose (f); return buf; }
INT setting_get_key_value(CHAR *valueptr, STRING *str) { CHAR *p, *p1; INT valuelen; p = valueptr; if(!p || !str) return 0; p1 = strchr(p, '\n'); if(!p1) valuelen = strlen(p); else valuelen = p1 - p; //str = string_assign(str, p); //string_truncate(str, valuelen); string_truncate(str, 0); string_nappend(str, p, valuelen); return valuelen; }
STRING *string_nappend(STRING *str, CHAR *newstr, INT len) { CHAR *p; INT newlen; if(!newstr) return NULL; if(!str) { str = string_new(newstr); str = string_truncate(str, len); return str; } if (len + str->len >= str->allocated_len ) { newlen = (len + str->len) * 3 / 2 + 1; p = os_new(CHAR, newlen); str->allocated_len = newlen; strcpy(p, str->str); } else { p = str->str; } //strncpy(p + str->len, newstr, len); strncat(p, newstr, len); if(p != str->str) { os_free(str->str); str->str = p; } str->len += len; str->str[str->len] = 0; return str; }
LIST * regex_transform( FRAME * frame, int flags ) { LIST * const l = lol_get( frame->args, 0 ); LIST * const pattern = lol_get( frame->args, 1 ); LIST * const indices_list = lol_get( frame->args, 2 ); int * indices = 0; int size; LIST * result = L0; if ( !list_empty( indices_list ) ) { int * p; LISTITER iter = list_begin( indices_list ); LISTITER const end = list_end( indices_list ); size = list_length( indices_list ); indices = (int *)BJAM_MALLOC( size * sizeof( int ) ); for ( p = indices; iter != end; iter = list_next( iter ) ) *p++ = atoi( object_str( list_item( iter ) ) ); } else { size = 1; indices = (int *)BJAM_MALLOC( sizeof( int ) ); *indices = 1; } { /* Result is cached and intentionally never freed */ regexp * const re = regex_compile( list_front( pattern ) ); LISTITER iter = list_begin( l ); LISTITER const end = list_end( l ); string buf[ 1 ]; string_new( buf ); for ( ; iter != end; iter = list_next( iter ) ) { if ( regexec( re, object_str( list_item( iter ) ) ) ) { int i = 0; for ( ; i < size; ++i ) { int const index = indices[ i ]; /* Skip empty submatches. Not sure it is right in all cases, * but surely is right for the case for which this routine * is optimized -- header scanning. */ if ( re->startp[ index ] != re->endp[ index ] ) { string_append_range( buf, re->startp[ index ], re->endp[ index ] ); result = list_push_back( result, object_new( buf->value ) ); string_truncate( buf, 0 ); } } } } string_free( buf ); } BJAM_FREE( indices ); return result; }
/* rule transform ( list * : pattern : indices * ) { indices ?= 1 ; local result ; for local e in $(list) { local m = [ MATCH $(pattern) : $(e) ] ; if $(m) { result += $(m[$(indices)]) ; } } return $(result) ; } */ LIST *regex_transform( FRAME *frame, int flags ) { LIST* l = lol_get( frame->args, 0 ); LIST* pattern = lol_get( frame->args, 1 ); LIST* indices_list = lol_get(frame->args, 2); int* indices = 0; int size; int* p; LIST* result = 0; string buf[1]; string_new(buf); if (indices_list) { size = list_length(indices_list); indices = (int*)BJAM_MALLOC(size*sizeof(int)); for(p = indices; indices_list; indices_list = indices_list->next) { *p++ = atoi(object_str(indices_list->value)); } } else { size = 1; indices = (int*)BJAM_MALLOC(sizeof(int)); *indices = 1; } { /* Result is cached and intentionally never freed */ regexp *re = regex_compile( pattern->value ); for(; l; l = l->next) { if( regexec( re, object_str( l->value ) ) ) { int i = 0; for(; i < size; ++i) { int index = indices[i]; /* Skip empty submatches. Not sure it's right in all cases, but surely is right for the case for which this routine is optimized -- header scanning. */ if (re->startp[index] != re->endp[index]) { string_append_range( buf, re->startp[index], re->endp[index] ); result = list_new( result, object_new( buf->value ) ); string_truncate( buf, 0 ); } } } } string_free( buf ); } BJAM_FREE(indices); return result; }
void string_pop_back( string* self ) { string_truncate( self, self->size - 1 ); }
static void canonicWindowsPath( char const * const path, int const path_length, string * const out ) { char const * last_element; unsigned long saved_size; char const * p; /* This is only called via path_key(), which initializes the cache. */ assert( path_key_cache ); if ( !path_length ) return; if ( path_length == 1 && path[ 0 ] == '\\' ) { string_push_back( out, '\\' ); return; } if ( path[ 1 ] == ':' && ( path_length == 2 || ( path_length == 3 && path[ 2 ] == '\\' ) ) ) { string_push_back( out, toupper( path[ 0 ] ) ); string_push_back( out, ':' ); string_push_back( out, '\\' ); return; } /* Find last '\\'. */ for ( p = path + path_length - 1; p >= path && *p != '\\'; --p ); last_element = p + 1; /* Special case '\' && 'D:\' - include trailing '\'. */ if ( p == path || p == path + 2 && path[ 1 ] == ':' ) ++p; if ( p >= path ) { char const * const dir = path; int const dir_length = p - path; OBJECT * const dir_obj = object_new_range( dir, dir_length ); int found; path_key_entry * const result = (path_key_entry *)hash_insert( path_key_cache, dir_obj, &found ); if ( !found ) { result->path = dir_obj; canonicWindowsPath( dir, dir_length, out ); result->key = object_new( out->value ); } else { object_free( dir_obj ); string_append( out, object_str( result->key ) ); } } if ( out->size && out->value[ out->size - 1 ] != '\\' ) string_push_back( out, '\\' ); saved_size = out->size; string_append_range( out, last_element, path + path_length ); { char const * const n = last_element; int const n_length = path + path_length - n; if ( !( n_length == 1 && n[ 0 ] == '.' ) && !( n_length == 2 && n[ 0 ] == '.' && n[ 1 ] == '.' ) ) { WIN32_FIND_DATA fd; HANDLE const hf = FindFirstFileA( out->value, &fd ); if ( hf != INVALID_HANDLE_VALUE ) { string_truncate( out, saved_size ); string_append( out, fd.cFileName ); FindClose( hf ); } } } }
void path_build( PATHNAME * f, string * file, int binding ) { struct dirinf root; struct dirinf dir; int g; file_build1( f, file ); /* Get info on root and dir for combining. */ dir_flags( f->f_root.ptr, f->f_root.len, &root ); dir_flags( f->f_dir.ptr, f->f_dir.len, &dir ); /* Combine. */ switch ( g = grid[ root.flags ][ dir.flags ] ) { case G_DIR: /* take dir */ string_append_range( file, f->f_dir.ptr, f->f_dir.ptr + f->f_dir.len ); break; case G_ROOT: /* take root */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); break; case G_VAD: /* root's dev + abs directory */ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len ); string_append_range( file, dir.dir.ptr, dir.dir.ptr + dir.dir.len ); break; case G_DRD: case G_DDD: /* root's dev:[dir] + rel directory */ string_append_range( file, f->f_root.ptr, f->f_root.ptr + f->f_root.len ); /* sanity checks: root ends with ] */ if ( file->value[file->size - 1] == ']' ) string_pop_back( file ); /* Add . if separating two -'s */ if ( g == G_DDD ) string_push_back( file, '.' ); /* skip [ of dir */ string_append_range( file, dir.dir.ptr + 1, dir.dir.ptr + 1 + dir.dir.len - 1 ); break; case G_VRD: /* root's dev + rel directory made abs */ string_append_range( file, root.dev.ptr, root.dev.ptr + root.dev.len ); string_push_back( file, '[' ); /* skip [. of rel dir */ string_append_range( file, dir.dir.ptr + 2, dir.dir.ptr + 2 + dir.dir.len - 2 ); break; } # ifdef DEBUG if ( DEBUG_SEARCH && ( root.flags || dir.flags ) ) printf( "%d x %d = %d (%s)\n", root.flags, dir.flags, grid[ root.flags ][ dir.flags ], file->value ); # endif /* * Now do the special :P modifier when no file was present. * (none) (none) * [dir1.dir2] [dir1] * [dir] [000000] * [.dir] (none) * [] [] */ if ( ( file->value[ file->size - 1 ] == ']' ) && f->parent ) { char * p = file->value + file->size; while ( p-- > file->value ) { if ( *p == '.' ) { /* If we've truncated everything and left with '[', return empty string. */ if ( p == file->value + 1 ) string_truncate( file, 0 ); else { string_truncate( file, p - file->value ); string_push_back( file, ']' ); } break; } if ( *p == '-' ) { /* handle .- or - */ if ( ( p > file->value ) && ( p[ -1 ] == '.' ) ) --p; *p++ = ']'; break; } if ( *p == '[' ) { if ( p[ 1 ] == ']' ) { /* CONSIDER: I don't see any use of this code. We immediately break, and 'p' is a local variable. */ p += 2; } else { string_truncate( file, p - file->value ); string_append( file, "[000000]" ); } break; } } } /* Now copy the file pieces. */ if ( f->f_base.len ) { string_append_range( file, f->f_base.ptr, f->f_base.ptr + f->f_base.len ); } /* If there is no suffix, we append a "." onto all generated names. This * keeps VMS from appending its own (wrong) idea of what the suffix should * be. */ if ( f->f_suffix.len ) string_append_range( file, f->f_suffix.ptr, f->f_suffix.ptr + f->f_suffix.len ); else if ( binding && f->f_base.len ) string_push_back( file, '.' ); if ( f->f_member.len ) { string_push_back( file, '(' ); string_append_range( file, f->f_member.ptr, f->f_member.ptr + f->f_member.len ); string_push_back( file, ')' ); } # ifdef DEBUG if ( DEBUG_SEARCH ) printf( "built %.*s + %.*s / %.*s suf %.*s mem %.*s -> %s\n", f->f_root.len, f->f_root.ptr, f->f_dir.len, f->f_dir.ptr, f->f_base.len, f->f_base.ptr, f->f_suffix.len, f->f_suffix.ptr, f->f_member.len, f->f_member.ptr, file->value ); # endif }
void var_defines( char *const* e, int preprocess ) { string buf[1]; string_new( buf ); for( ; *e; e++ ) { char *val; # ifdef OS_MAC /* On the mac (MPW), the var=val is actually var\0val */ /* Think different. */ if( ( val = strchr( *e, '=' ) ) || ( val = *e + strlen( *e ) ) ) # else if( val = strchr( *e, '=' ) ) # endif { LIST *l = L0; char *pp, *p; # ifdef OPT_NO_EXTERNAL_VARIABLE_SPLIT char split = '\0'; # else # ifdef OS_MAC char split = ','; # else char split = ' '; # endif # endif size_t len = strlen(val + 1); int quoted = val[1] == '"' && val[len] == '"' && len > 1; if ( quoted && preprocess ) { string_append_range( buf, val + 2, val + len ); l = list_new( l, newstr( buf->value ) ); string_truncate( buf, 0 ); } else { /* Split *PATH at :'s, not spaces */ if( val - 4 >= *e ) { if( !strncmp( val - 4, "PATH", 4 ) || !strncmp( val - 4, "Path", 4 ) || !strncmp( val - 4, "path", 4 ) ) split = SPLITPATH; } /* Do the split */ for( pp = val + 1; preprocess && (p = strchr( pp, split )) != 0; pp = p + 1 ) { string_append_range( buf, pp, p ); l = list_new( l, newstr( buf->value ) ); string_truncate( buf, 0 ); } l = list_new( l, newstr( pp ) ); } /* Get name */ string_append_range( buf, *e, val ); var_set( buf->value, l, VAR_SET ); string_truncate( buf, 0 ); } } string_free( buf ); }
void var_defines( struct module_t * module, char * const * e, int preprocess ) { string buf[ 1 ]; string_new( buf ); for ( ; *e; ++e ) { char * val; if ( ( val = strchr( *e, '=' ) ) #if defined( OS_MAC ) /* On the mac (MPW), the var=val is actually var\0val */ /* Think different. */ || ( val = *e + strlen( *e ) ) #endif ) { LIST * l = L0; size_t const len = strlen( val + 1 ); int const quoted = ( val[ 1 ] == '"' ) && ( val[ len ] == '"' ) && ( len > 1 ); if ( quoted && preprocess ) { string_append_range( buf, val + 2, val + len ); l = list_push_back( l, object_new( buf->value ) ); string_truncate( buf, 0 ); } else { char * p; char * pp; char split = #if defined( OPT_NO_EXTERNAL_VARIABLE_SPLIT ) '\0' #elif defined( OS_MAC ) ',' #else ' ' #endif ; /* Split *PATH at :'s, not spaces. */ if ( val - 4 >= *e ) { if ( !strncmp( val - 4, "PATH", 4 ) || !strncmp( val - 4, "Path", 4 ) || !strncmp( val - 4, "path", 4 ) ) split = SPLITPATH; } /* Do the split. */ for ( pp = val + 1; preprocess && ( ( p = strchr( pp, split ) ) != 0 ); pp = p + 1 ) { string_append_range( buf, pp, p ); l = list_push_back( l, object_new( buf->value ) ); string_truncate( buf, 0 ); } l = list_push_back( l, object_new( pp ) ); } /* Get name. */ string_append_range( buf, *e, val ); { OBJECT * const varname = object_new( buf->value ); var_set( module, varname, l, VAR_SET ); object_free( varname ); } string_truncate( buf, 0 ); } } string_free( buf ); }
void ShortPathToLongPath( char * short_path, string * out ) { const char * new_element; unsigned long saved_size; char * p; if ( short_path[0] == '\0' ) { return; } if ( short_path[0] == '\\' && short_path[1] == '\0') { string_push_back( out, '\\' ); return; } if ( short_path[1] == ':' && ( short_path[2] == '\0' || ( short_path[2] == '\\' && short_path[3] == '\0' ) ) ) { string_push_back( out, toupper( short_path[0] ) ); string_push_back( out, ':' ); string_push_back( out, '\\' ); return; } /* '/' already handled. */ if ( ( p = strrchr( short_path, '\\' ) ) ) { char saved; new_element = p + 1; /* special case \ */ if ( p == short_path ) ++p; /* special case D:\ */ if ( p == short_path + 2 && short_path[1] == ':' ) ++p; saved = *p; *p = '\0'; path_write_key( short_path, out ); *p = saved; } else { new_element = short_path; } if ( out->size && out->value[ out->size - 1 ] != '\\' ) { string_push_back( out, '\\' ); } saved_size = out->size; string_append( out, new_element ); if ( ! ( new_element[0] == '.' && new_element[1] == '\0' || new_element[0] == '.' && new_element[1] == '.' && new_element[2] == '\0' ) ) { WIN32_FIND_DATA fd; HANDLE hf = 0; hf = FindFirstFile( out->value, &fd ); /* If the file exists, replace the name. */ if ( hf != INVALID_HANDLE_VALUE ) { string_truncate( out, saved_size ); string_append( out, fd.cFileName ); FindClose( hf ); } } }
void timestamp( char *target, time_t *time ) { PATHNAME f1, f2; BINDING binding, *b = &binding; string buf[1]; # ifdef DOWNSHIFT_PATHS string path; char *p; string_copy( &path, target ); p = path.value; do *p = tolower( *p ); while( *p++ ); target = path.value; # endif string_new( buf ); if( !bindhash ) bindhash = hashinit( sizeof( BINDING ), "bindings" ); /* Quick path - is it there? */ b->name = target; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( target ); /* never freed */ if( b->progress != BIND_INIT ) goto afterscanning; b->progress = BIND_NOENTRY; /* Not found - have to scan for it */ path_parse( target, &f1 ); /* Scan directory if not already done so */ { BINDING binding, *b = &binding; f2 = f1; f2.f_grist.len = 0; path_parent( &f2 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( buf->value ); /* never freed */ if( !( b->flags & BIND_SCANNED ) ) { file_dirscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } /* Scan archive if not already done so */ if( f1.f_member.len ) { BINDING binding, *b = &binding; f2 = f1; f2.f_grist.len = 0; f2.f_member.len = 0; string_truncate( buf, 0 ); path_build( &f2, buf, 0 ); b->name = buf->value; b->time = b->flags = 0; b->progress = BIND_INIT; if( hashenter( bindhash, (HASHDATA **)&b ) ) b->name = newstr( buf->value ); /* never freed */ if( !( b->flags & BIND_SCANNED ) ) { file_archscan( buf->value, time_enter, bindhash ); b->flags |= BIND_SCANNED; } } afterscanning: if( b->progress == BIND_SPOTTED ) { if( file_time( b->name, &b->time ) < 0 ) b->progress = BIND_MISSING; else b->progress = BIND_FOUND; } *time = b->progress == BIND_FOUND ? b->time : 0; string_free( buf ); # ifdef DOWNSHIFT_PATHS string_free( &path ); #endif }
void file_dirscan( char * dir, scanback func, void * closure ) { PROFILE_ENTER( FILE_DIRSCAN ); file_info_t * d = 0; dir = short_path_to_long_path( dir ); /* First enter directory itself */ d = file_query( dir ); if ( !d || !d->is_dir ) { PROFILE_EXIT( FILE_DIRSCAN ); return; } if ( !d->files ) { PATHNAME f; string filespec[ 1 ]; string filename[ 1 ]; long handle; int ret; struct _finddata_t finfo[ 1 ]; LIST * files = L0; int d_length = strlen( d->name ); memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = d->name; f.f_dir.len = d_length; /* Now enter contents of directory */ /* Prepare file search specification for the findfirst() API. */ if ( d_length == 0 ) string_copy( filespec, ".\\*" ); else { /* * We can not simply assume the given folder name will never include * its trailing path separator or otherwise we would not support the * Windows root folder specified without its drive letter, i.e. '\'. */ char trailingChar = d->name[ d_length - 1 ] ; string_copy( filespec, d->name ); if ( ( trailingChar != '\\' ) && ( trailingChar != '/' ) ) string_append( filespec, "\\" ); string_append( filespec, "*" ); } if ( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir ); #if defined(__BORLANDC__) && __BORLANDC__ < 0x550 if ( ret = findfirst( filespec->value, finfo, FA_NORMAL | FA_DIREC ) ) { string_free( filespec ); PROFILE_EXIT( FILE_DIRSCAN ); return; } string_new ( filename ); while ( !ret ) { file_info_t * ff = 0; f.f_base.ptr = finfo->ff_name; f.f_base.len = strlen( finfo->ff_name ); string_truncate( filename, 0 ); path_build( &f, filename ); files = list_new( files, newstr(filename->value) ); ff = file_info( filename->value ); ff->is_file = finfo->ff_attrib & FA_DIREC ? 0 : 1; ff->is_dir = finfo->ff_attrib & FA_DIREC ? 1 : 0; ff->size = finfo->ff_fsize; ff->time = (finfo->ff_ftime << 16) | finfo->ff_ftime; ret = findnext( finfo ); } # else handle = _findfirst( filespec->value, finfo ); if ( ret = ( handle < 0L ) ) { string_free( filespec ); PROFILE_EXIT( FILE_DIRSCAN ); return; } string_new( filename ); while ( !ret ) { file_info_t * ff = 0; f.f_base.ptr = finfo->name; f.f_base.len = strlen( finfo->name ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); files = list_new( files, newstr( filename->value ) ); ff = file_info( filename->value ); ff->is_file = finfo->attrib & _A_SUBDIR ? 0 : 1; ff->is_dir = finfo->attrib & _A_SUBDIR ? 1 : 0; ff->size = finfo->size; ff->time = finfo->time_write; ret = _findnext( handle, finfo ); } _findclose( handle ); # endif string_free( filename ); string_free( filespec ); d->files = files; } /* Special case \ or d:\ : enter it */ { unsigned long len = strlen(d->name); if ( len == 1 && d->name[0] == '\\' ) (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); else if ( len == 3 && d->name[1] == ':' ) { (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); /* We've just entered 3-letter drive name spelling (with trailing slash), into the hash table. Now enter two-letter variant, without trailing slash, so that if we try to check whether "c:" exists, we hit it. Jam core has workarounds for that. Given: x = c:\whatever\foo ; p = $(x:D) ; p2 = $(p:D) ; There will be no trailing slash in $(p), but there will be one in $(p2). But, that seems rather fragile. */ d->name[2] = 0; (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); } } /* Now enter contents of directory */ if ( d->files ) { LIST * files = d->files; while ( files ) { file_info_t * ff = file_info( files->string ); (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time ); files = list_next( files ); } } PROFILE_EXIT( FILE_DIRSCAN ); }
TARGET* search_for_target ( char * name, LIST* search_path ) { PATHNAME f[1]; string buf[1]; LOCATED_TARGET lt, *lta = < time_t time; int found = 0; TARGET* result; string_new( buf ); path_parse( name, f ); f->f_grist.ptr = 0; f->f_grist.len = 0; while( search_path ) { f->f_root.ptr = search_path->string; f->f_root.len = strlen( search_path->string ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); lt.file_name = buf->value ; if (! located_targets ) located_targets = hashinit( sizeof(LOCATED_TARGET), "located targets" ); if ( hashcheck( located_targets, (HASHDATA **)<a ) ) { return lta->target; } timestamp( buf->value, &time ); if (time) { found = 1; break; } search_path = list_next( search_path ); } if ( ! found ) { f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); timestamp( buf->value, &time ); } result = bindtarget( name ); result->boundname = newstr( buf->value ); result->time = time; result->binding = time ? T_BIND_EXISTS : T_BIND_MISSING; call_bind_rule( result->name, result->boundname ); string_free( buf ); return result; }
LIST * var_expand( LIST *l, char *in, char *end, LOL *lol, int cancopyin ) { char out_buf[ MAXSYM ]; string buf[1]; string out1[1]; /* Temporary buffer */ size_t prefix_length; char *out; char *inp = in; char *ov; /* for temp copy of variable in outbuf */ int depth; if( DEBUG_VAREXP ) printf( "expand '%.*s'\n", end - in, in ); /* This gets alot of cases: $(<) and $(>) */ if( in[0] == '$' && in[1] == '(' && in[3] == ')' && !in[4] ) { switch( in[2] ) { case '1': case '<': return list_copy( l, lol_get( lol, 0 ) ); case '2': case '>': return list_copy( l, lol_get( lol, 1 ) ); } } /* Just try simple copy of in to out. */ while( in < end ) if( *in++ == '$' && *in == '(' ) goto expand; /* No variables expanded - just add copy of input string to list. */ /* Cancopyin is an optimization: if the input was already a list */ /* item, we can use the copystr() to put it on the new list. */ /* Otherwise, we use the slower newstr(). */ if( cancopyin ) { return list_new( l, copystr( inp ) ); } else { LIST* r; string_new( buf ); string_append_range( buf, inp, end ); r = list_new( l, newstr( buf->value) ); string_free( buf ); return r; } expand: string_new( buf ); string_append_range( buf, inp, in - 1); /* copy the part before '$'. */ /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf $ * ^ ^ * out_buf out * * * We just copied the $ of $(...), so back up one on the output. * We now find the matching close paren, copying the variable and * modifiers between the $( and ) temporarily into out_buf, so that * we can replace :'s with MAGIC_COLON. This is necessary to avoid * being confused by modifier values that are variables containing * :'s. Ugly. */ depth = 1; inp = ++in; /* skip over the '(' */ while( in < end && depth ) { switch( *in++ ) { case '(': depth++; break; case ')': depth--; break; } } /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ ^ * inp in end */ prefix_length = buf->size; string_append_range( buf, inp, in - 1 ); out = buf->value + prefix_length; for ( ov = out; ov < buf->value + buf->size; ++ov ) { switch( *ov ) { case ':': *ov = MAGIC_COLON; break; case '[': *ov = MAGIC_LEFT; break; case ']': *ov = MAGIC_RIGHT; break; } } /* * Input so far (ignore blanks): * * stuff-in-outbuf $(variable) remainder * ^ ^ * in end * Output so far: * * stuff-in-outbuf variable * ^ ^ ^ * out_buf out ov * * Later we will overwrite 'variable' in out_buf, but we'll be * done with it by then. 'variable' may be a multi-element list, * so may each value for '$(variable element)', and so may 'remainder'. * Thus we produce a product of three lists. */ { LIST *variables = 0; LIST *remainder = 0; LIST *vars; /* Recursively expand variable name & rest of input */ if( out < ov ) variables = var_expand( L0, out, ov, lol, 0 ); if( in < end ) remainder = var_expand( L0, in, end, lol, 0 ); /* Now produce the result chain */ /* For each variable name */ for( vars = variables; vars; vars = list_next( vars ) ) { LIST *value, *evalue = 0; char *colon; char *bracket; string variable[1]; char *varname; int sub1 = 0, sub2 = -1; VAR_EDITS edits; /* Look for a : modifier in the variable name */ /* Must copy into varname so we can modify it */ string_copy( variable, vars->string ); varname = variable->value; if( colon = strchr( varname, MAGIC_COLON ) ) { string_truncate( variable, colon - varname ); var_edit_parse( colon + 1, &edits ); } /* Look for [x-y] subscripting */ /* sub1 and sub2 are x and y. */ if ( bracket = strchr( varname, MAGIC_LEFT ) ) { /* ** Make all syntax errors in [] subscripting ** result in the same behavior: silenty return an empty ** expansion (by setting sub2 = 0). Brute force parsing; ** May get moved into yacc someday. */ char *s = bracket + 1; string_truncate( variable, bracket - varname ); do /* so we can use "break" */ { /* Allow negative indexes. */ if (! isdigit( *s ) && ! ( *s == '-') ) { sub2 = 0; break; } sub1 = atoi(s); /* Skip over the first symbol, which is either a digit or dash. */ s++; while ( isdigit( *s ) ) s++; if ( *s == MAGIC_RIGHT ) { sub2 = sub1; break; } if ( *s != '-') { sub2 = 0; break; } s++; if ( *s == MAGIC_RIGHT ) { sub2 = -1; break; } if (! isdigit( *s ) && ! ( *s == '-') ) { sub2 = 0; break; } /* First, compute the index of the last element. */ sub2 = atoi(s); s++; while ( isdigit( *s ) ) s++; if ( *s != MAGIC_RIGHT) sub2 = 0; } while (0); /* ** Anything but the end of the string, or the colon ** introducing a modifier is a syntax error. */ s++; if (*s && *s != MAGIC_COLON) sub2 = 0; *bracket = '\0'; } /* Get variable value, specially handling $(<), $(>), $(n) */ if( varname[0] == '<' && !varname[1] ) value = lol_get( lol, 0 ); else if( varname[0] == '>' && !varname[1] ) value = lol_get( lol, 1 ); else if( varname[0] >= '1' && varname[0] <= '9' && !varname[1] ) value = lol_get( lol, varname[0] - '1' ); else value = var_get( varname ); /* Handle negitive indexes: part two. */ { int length = list_length( value ); if (sub1 < 0) sub1 = length + sub1; else sub1 -= 1; if (sub2 < 0) sub2 = length + 1 + sub2 - sub1; else sub2 -= sub1; /* ** The "sub2 < 0" test handles the semantic error ** of sub2 < sub1. */ if ( sub2 < 0 ) sub2 = 0; } /* The fast path: $(x) - just copy the variable value. */ /* This is only an optimization */ if( out == out_buf && !bracket && !colon && in == end ) { string_free( variable ); l = list_copy( l, value ); continue; } /* Handle start subscript */ while( sub1 > 0 && value ) --sub1, value = list_next( value ); /* Empty w/ :E=default? */ if( !value && colon && edits.empty.ptr ) evalue = value = list_new( L0, newstr( edits.empty.ptr ) ); /* For each variable value */ string_new( out1 ); for( ; value; value = list_next( value ) ) { LIST *rem; size_t postfix_start; /* Handle end subscript (length actually) */ if( sub2 >= 0 && --sub2 < 0 ) break; string_truncate( buf, prefix_length ); /* Apply : mods, if present */ if( colon && edits.filemods ) var_edit_file( value->string, out1, &edits ); else string_append( out1, value->string ); if( colon && ( edits.upshift || edits.downshift || edits.to_slashes || edits.to_windows ) ) var_edit_shift( out1, &edits ); /* Handle :J=joinval */ /* If we have more values for this var, just */ /* keep appending them (with the join value) */ /* rather than creating separate LIST elements. */ if( colon && edits.join.ptr && ( list_next( value ) || list_next( vars ) ) ) { string_append( out1, edits.join.ptr ); continue; } string_append( buf, out1->value ); string_free( out1 ); string_new( out1 ); /* If no remainder, append result to output chain. */ if( in == end ) { l = list_new( l, newstr( buf->value ) ); continue; } /* For each remainder, append the complete string */ /* to the output chain. */ /* Remember the end of the variable expansion so */ /* we can just tack on each instance of 'remainder' */ postfix_start = buf->size; for( rem = remainder; rem; rem = list_next( rem ) ) { string_truncate( buf, postfix_start ); string_append( buf, rem->string ); l = list_new( l, newstr( buf->value ) ); } } string_free( out1 ); /* Toss used empty */ if( evalue ) list_free( evalue ); string_free( variable ); } /* variables & remainder were gifts from var_expand */ /* and must be freed */ if( variables ) list_free( variables ); if( remainder) list_free( remainder ); if( DEBUG_VAREXP ) { printf( "expanded to " ); list_print( l ); printf( "\n" ); } string_free( buf ); return l; } }
void file_dirscan( char * dir, scanback func, void * closure ) { PATHNAME f; string filename[ 1 ]; unsigned char fullPath[ 512 ]; FSSpec spec; WDPBRec vol; Str63 volName; CInfoPBRec lastInfo; int index = 1; /* First enter directory itself. */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dir; f.f_dir.len = strlen(dir); if ( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dir ); /* Special case ":" - enter it */ if ( ( f.f_dir.len == 1 ) && ( f.f_dir.ptr[0] == ':' ) ) (*func)( closure, dir, 0 /* not stat()'ed */, (time_t)0 ); /* Now enter contents of directory */ vol.ioNamePtr = volName; if ( PBHGetVolSync( &vol ) ) return; CopyC2PStr( dir, fullPath ); if ( FSMakeFSSpec( vol.ioWDVRefNum, vol.ioWDDirID, fullPath, &spec ) ) return; lastInfo.dirInfo.ioVRefNum = spec.vRefNum; lastInfo.dirInfo.ioDrDirID = spec.parID; lastInfo.dirInfo.ioNamePtr = spec.name; lastInfo.dirInfo.ioFDirIndex = 0; lastInfo.dirInfo.ioACUser = 0; if ( PBGetCatInfoSync( &lastInfo ) ) return; if ( !( lastInfo.dirInfo.ioFlAttrib & 0x10 ) ) return; /* ioDrDirID must be reset each time. */ spec.parID = lastInfo.dirInfo.ioDrDirID; string_new( filename ); for ( ; ; ) { lastInfo.dirInfo.ioVRefNum = spec.vRefNum; lastInfo.dirInfo.ioDrDirID = spec.parID; lastInfo.dirInfo.ioNamePtr = fullPath; lastInfo.dirInfo.ioFDirIndex = index++; if ( PBGetCatInfoSync( &lastInfo ) ) return; f.f_base.ptr = (char *)fullPath + 1; f.f_base.len = *fullPath; string_truncate( filename, 0 ); path_build( &f, filename, 0 ); (*func)( closure, filename->value, 0 /* not stat()'ed */, (time_t)0 ); } string_free( filename ); }
OBJECT * search( OBJECT * target, time_t *time, OBJECT * * another_target, int file ) { PATHNAME f[1]; LIST * varlist; string buf[1]; int found = 0; /* Will be set to 1 if target location is specified via LOCATE. */ int explicitly_located = 0; OBJECT * boundname = 0; OBJECT * varname; if ( another_target ) *another_target = 0; if (! explicit_bindings ) explicit_bindings = hashinit( sizeof(BINDING), "explicitly specified locations"); string_new( buf ); /* Parse the filename */ path_parse( object_str( target ), f ); f->f_grist.ptr = 0; f->f_grist.len = 0; varname = object_new( "LOCATE" ); varlist = var_get( varname ); object_free( varname ); if ( varlist ) { OBJECT * key; f->f_root.ptr = object_str( varlist->value ); f->f_root.len = strlen( object_str( varlist->value ) ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "locate %s: %s\n", object_str( target ), buf->value ); explicitly_located = 1; key = object_new( buf->value ); timestamp( key, time ); object_free( key ); found = 1; } else if ( ( varname = object_new( "SEARCH" ), varlist = var_get( varname ), object_free( varname ), varlist ) ) { while ( varlist ) { BINDING b, *ba = &b; file_info_t *ff; OBJECT * key; OBJECT * test_path; f->f_root.ptr = object_str( varlist->value ); f->f_root.len = strlen( object_str( varlist->value ) ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); test_path = object_new( buf->value ); key = path_as_key( test_path ); object_free( test_path ); ff = file_query( key ); timestamp( key, time ); b.binding = key; if ( hashcheck( explicit_bindings, (HASHDATA**)&ba ) ) { if ( DEBUG_SEARCH ) printf(" search %s: found explicitly located target %s\n", object_str( target ), object_str( ba->target ) ); if ( another_target ) *another_target = ba->target; found = 1; object_free( key ); break; } else if ( ff && ff->time ) { if ( !file || ff->is_file ) { found = 1; object_free( key ); break; } } object_free( key ); varlist = list_next( varlist ); } } if ( !found ) { /* Look for the obvious */ /* This is a questionable move. Should we look in the */ /* obvious place if SEARCH is set? */ OBJECT * key; f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); key = object_new( buf->value ); timestamp( key, time ); object_free( key ); } boundname = object_new( buf->value ); string_free( buf ); if ( explicitly_located ) { BINDING b; BINDING * ba = &b; OBJECT * key = path_as_key( boundname ); b.binding = key; b.target = target; /* CONSIDER: we probably should issue a warning is another file is explicitly bound to the same location. This might break compatibility, though. */ if ( !hashenter( explicit_bindings, (HASHDATA * *)&ba ) ) { object_free( key ); } } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); return boundname; }
OBJECT * search( OBJECT * target, time_t *time, OBJECT * * another_target, int file ) { PATHNAME f[1]; LIST * varlist; string buf[1]; int found = 0; /* Will be set to 1 if target location is specified via LOCATE. */ int explicitly_located = 0; OBJECT * boundname = 0; if ( another_target ) *another_target = 0; if (! explicit_bindings ) explicit_bindings = hashinit( sizeof(BINDING), "explicitly specified locations"); string_new( buf ); /* Parse the filename */ path_parse( object_str( target ), f ); f->f_grist.ptr = 0; f->f_grist.len = 0; varlist = var_get( root_module(), constant_LOCATE ); if ( !list_empty( varlist ) ) { OBJECT * key; f->f_root.ptr = object_str( list_front( varlist ) ); f->f_root.len = strlen( object_str( list_front( varlist ) ) ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "locate %s: %s\n", object_str( target ), buf->value ); explicitly_located = 1; key = object_new( buf->value ); timestamp( key, time ); object_free( key ); found = 1; } else if ( varlist = var_get( root_module(), constant_SEARCH ), !list_empty( varlist ) ) { LISTITER iter = list_begin( varlist ), end = list_end( varlist ); for ( ; iter != end; iter = list_next( iter ) ) { BINDING * ba; file_info_t *ff; OBJECT * key; OBJECT * test_path; f->f_root.ptr = object_str( list_item( iter ) ); f->f_root.len = strlen( object_str( list_item( iter ) ) ); string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); test_path = object_new( buf->value ); key = path_as_key( test_path ); object_free( test_path ); ff = file_query( key ); timestamp( key, time ); if ( ( ba = (BINDING *)hash_find( explicit_bindings, key ) ) ) { if ( DEBUG_SEARCH ) printf(" search %s: found explicitly located target %s\n", object_str( target ), object_str( ba->target ) ); if ( another_target ) *another_target = ba->target; found = 1; object_free( key ); break; } else if ( ff && ff->time ) { if ( !file || ff->is_file ) { found = 1; object_free( key ); break; } } object_free( key ); } } if ( !found ) { /* Look for the obvious */ /* This is a questionable move. Should we look in the */ /* obvious place if SEARCH is set? */ OBJECT * key; f->f_root.ptr = 0; f->f_root.len = 0; string_truncate( buf, 0 ); path_build( f, buf, 1 ); if ( DEBUG_SEARCH ) printf( "search %s: %s\n", object_str( target ), buf->value ); key = object_new( buf->value ); timestamp( key, time ); object_free( key ); } boundname = object_new( buf->value ); string_free( buf ); if ( explicitly_located ) { int found; BINDING * ba; OBJECT * key = path_as_key( boundname ); /* CONSIDER: we probably should issue a warning is another file is explicitly bound to the same location. This might break compatibility, though. */ ba = (BINDING *)hash_insert( explicit_bindings, key, &found ); if ( !found ) { ba->binding = key; ba->target = target; } else { object_free( key ); } } /* prepare a call to BINDRULE if the variable is set */ call_bind_rule( target, boundname ); return boundname; }
void file_dirscan( OBJECT * dir, scanback func, void * closure ) { PROFILE_ENTER( FILE_DIRSCAN ); file_info_t * d = 0; d = file_query( dir ); if ( !d || !d->is_dir ) { PROFILE_EXIT( FILE_DIRSCAN ); return; } if ( ! d->files ) { LIST* files = L0; PATHNAME f; DIR *dd; STRUCT_DIRENT *dirent; string filename[1]; const char * dirstr = object_str( dir ); /* First enter directory itself */ memset( (char *)&f, '\0', sizeof( f ) ); f.f_dir.ptr = dirstr; f.f_dir.len = strlen( dirstr ); dirstr = *dirstr ? dirstr : "."; /* Now enter contents of directory. */ if ( !( dd = opendir( dirstr ) ) ) { PROFILE_EXIT( FILE_DIRSCAN ); return; } if ( DEBUG_BINDSCAN ) printf( "scan directory %s\n", dirstr ); string_new( filename ); while ( ( dirent = readdir( dd ) ) ) { OBJECT * filename_obj; # ifdef old_sinix /* Broken structure definition on sinix. */ f.f_base.ptr = dirent->d_name - 2; # else f.f_base.ptr = dirent->d_name; # endif f.f_base.len = strlen( f.f_base.ptr ); string_truncate( filename, 0 ); path_build( &f, filename, 0 ); filename_obj = object_new( filename->value ); files = list_new( files, filename_obj ); file_query( filename_obj ); } string_free( filename ); closedir( dd ); d->files = files; } /* Special case / : enter it */ { if ( strcmp( object_str( d->name ), "/" ) == 0 ) (*func)( closure, d->name, 1 /* stat()'ed */, d->time ); } /* Now enter contents of directory */ if ( d->files ) { LIST * files = d->files; while ( files ) { file_info_t * ff = file_info( files->value ); (*func)( closure, ff->name, 1 /* stat()'ed */, ff->time ); files = list_next( files ); } } PROFILE_EXIT( FILE_DIRSCAN ); }
void var_string_to_file( const char * in, int insize, const char * out, LOL * lol ) { const char * ine = in+insize; FILE * out_file = 0; if ( strcmp( out, "STDOUT" ) == 0 ) { out_file = stdout; } else if ( strcmp( out, "STDERR" ) == 0 ) { out_file = stderr; } else { /* Handle "path to file" filenames. */ string out_name; if ( out[0] == '"' && out[strlen(out) - 1] == '"' ) { string_copy(&out_name,out+1); string_truncate(&out_name,out_name.size-1); } else { string_copy(&out_name,out); } out_file = fopen( out_name.value, "w" ); if (!out_file) { printf( "failed to write output file '%s'!\n", out_name.value ); exit( EXITBAD ); } string_free(&out_name); } while( *in && in < ine ) { int dollar = 0; const char * output_0 = in; const char * output_1 = in; /* Copy white space */ while ( output_1 < ine && *output_1 && isspace( *output_1 ) ) { ++output_1; } if ( output_0 < output_1 ) { fwrite(output_0,output_1-output_0,1,out_file); } output_0 = output_1; /* Copy non-white space, watching for variables */ while( output_1 < ine && *output_1 && !isspace( *output_1 ) ) { if( output_1[0] == '$' && output_1[1] && output_1[1] == '(' ) { dollar++; } ++output_1; } /* If a variable encountered, expand it and and embed the */ /* space-separated members of the list in the output. */ if( dollar ) { LIST *l; l = var_expand( L0, (char*)output_0, (char*)output_1, lol, 0 ); while ( l ) { fputs( l->string, out_file ); l = list_next( l ); if ( l ) fputc( ' ', out_file ); } list_free( l ); } else if ( output_0 < output_1 ) { fwrite(output_0,output_1-output_0,1,out_file); } in = output_1; } if ( out_file != stdout && out_file != stderr ) { fflush( out_file ); fclose( out_file ); } }