wchar_t *wrealpath(const wchar_t *pathname, wchar_t *resolved_path) { char *tmp = wutil_wcs2str(pathname); char *narrow_res = realpath( tmp, 0 ); wchar_t *res; if( !narrow_res ) return 0; if( resolved_path ) { wchar_t *tmp2 = str2wcs( narrow_res ); wcslcpy( resolved_path, tmp2, PATH_MAX ); free( tmp2 ); res = resolved_path; } else { res = str2wcs( narrow_res ); } free( narrow_res ); return res; }
/** Set up default values for various variables if not defined. */ static void env_set_defaults() { if( env_get_string(L"USER").missing() ) { struct passwd *pw = getpwuid( getuid()); wchar_t *unam = str2wcs( pw->pw_name ); env_set( L"USER", unam, ENV_GLOBAL ); free( unam ); } if( env_get_string(L"HOME").missing() ) { const env_var_t unam = env_get_string( L"USER" ); char *unam_narrow = wcs2str( unam.c_str() ); struct passwd *pw = getpwnam( unam_narrow ); wchar_t *dir = str2wcs( pw->pw_dir ); env_set( L"HOME", dir, ENV_GLOBAL ); free( dir ); free( unam_narrow ); } env_set_pwd(); }
wcstring str2wcstring( const char *in ) { wchar_t *tmp = str2wcs(in); wcstring result = tmp; free(tmp); return result; }
wcstring str2wcstring( const std::string &in ) { wchar_t *tmp = str2wcs(in.c_str()); wcstring result = tmp; free(tmp); return result; }
wchar *Sys_GetClipboardTextW(void) { char *tmp; wchar *wtmp = NULL; if (SDL_HasClipboardText()) { tmp = SDL_GetClipboardText(); wtmp = str2wcs(tmp); free(tmp); } return wtmp; }
/** Read lines of input from the specified file, unescape them and insert them into the specified list. */ static void read_array( FILE* file, wcstring_list_t &comp ) { std::vector<char> buffer; int c; wchar_t *wcs; while( !feof( file ) ) { buffer.clear(); while( 1 ) { c = getc( file ); if( c == EOF ) { break; } if( c == '\n' ) { break; } buffer.push_back(static_cast<char>(c)); } if( ! buffer.empty() ) { buffer.push_back(0); wcs = str2wcs( &buffer.at(0) ); if( wcs ) { wcstring tmp = wcs; if (unescape_string(tmp, 0)) { comp.push_back(tmp); } free( wcs ); } } } }
/** Get environment variable value. The resulting string needs to be free'd. */ static wchar_t *fishd_env_get( const wchar_t *key ) { char *nres, *nkey; wchar_t *res; nkey = wcs2str( key ); nres = getenv( nkey ); free( nkey ); if( nres ) { return str2wcs( nres ); } else { res = env_universal_common_get( key ); if( res ) res = wcsdup( res ); return res; } }
/** Returns the name of the save file for a mode. \param context a halloc context used to allocate memory \param name the name of the hstory mode \param suffix an optional file suffix */ static wchar_t *history_filename( void *context, const wchar_t *name, const wchar_t *suffix ) { char *env; wchar_t *res; if( !current_mode ) return 0; if( env = getenv( "FISH_HISTORY" ) ) { res = str2wcs( env ); } else { wchar_t *path = path_get_config( context ); if( !path ) return 0; res = wcsdupcat( path, L"/", name, L"_history", suffix?suffix:(void *)0); } halloc_register_function( context, &free, res ); return res; }
/** Initialize various subsystems. This also closes stdin and replaces it with a copy of stderr, so the reading of completion strings must be done before init is called. */ static void init( int mangle_descriptors, int out ) { struct sigaction act; static struct termios pager_modes; char *term; if( mangle_descriptors ) { /* Make fd 1 output to screen, and use some other fd for writing the resulting output back to the caller */ int in; out = dup( 1 ); close(1); close(0); /* OK to not use CLO_EXEC here because fish_pager is single threaded */ if( (in = open( ttyname(2), O_RDWR )) != -1 ) { if( dup2( 2, 1 ) == -1 ) { debug( 0, _(L"Could not set up output file descriptors for pager") ); exit( 1 ); } if( dup2( in, 0 ) == -1 ) { debug( 0, _(L"Could not set up input file descriptors for pager") ); exit( 1 ); } } else { debug( 0, _(L"Could not open tty for pager") ); exit( 1 ); } } if( !(out_file = fdopen( out, "w" )) ) { debug( 0, _(L"Could not initialize result pipe" ) ); exit( 1 ); } env_universal_init( 0, 0, 0, 0); input_common_init( &interrupt_handler ); output_set_writer( &pager_buffered_writer ); sigemptyset( & act.sa_mask ); act.sa_flags=0; act.sa_handler=SIG_DFL; act.sa_flags = 0; act.sa_handler= &handle_winch; if( sigaction( SIGWINCH, &act, 0 ) ) { wperror( L"sigaction" ); exit(1); } handle_winch( 0 ); /* Set handler for window change events */ tcgetattr(0,&pager_modes); /* get the current terminal modes */ memcpy( &saved_modes, &pager_modes, sizeof(saved_modes)); /* save a copy so we can reset the terminal later */ pager_modes.c_lflag &= ~ICANON; /* turn off canonical mode */ pager_modes.c_lflag &= ~ECHO; /* turn off echo mode */ pager_modes.c_cc[VMIN]=1; pager_modes.c_cc[VTIME]=0; /* */ if( tcsetattr(0,TCSANOW,&pager_modes)) /* set the new modes */ { wperror(L"tcsetattr"); exit(1); } if( setupterm( 0, STDOUT_FILENO, 0) == ERR ) { debug( 0, _(L"Could not set up terminal") ); exit(1); } term = getenv("TERM"); if( term ) { wchar_t *wterm = str2wcs(term); output_set_term( wterm ); free( wterm ); } /* Infer term256 support */ char *fish_term256 = getenv("fish_term256"); bool support_term256; if (fish_term256) { support_term256 = from_string<bool>(fish_term256); } else { support_term256 = term && strstr(term, "256color"); } output_set_supports_term256(support_term256); }
int main( int argc, char **argv ) { int i; int is_quoted=0; wcstring_list_t comp; wchar_t *prefix = 0; int mangle_descriptors = 0; int result_fd = -1; set_main_thread(); setup_fork_guards(); /* This initialization is made early, so that the other init code can use global_context for memory managment */ program_name = L"fish_pager"; wsetlocale( LC_ALL, L"" ); /* The call signature for fish_pager is a mess. Because we want to be able to upgrade fish without breaking running instances, we need to support all previous modes. Unfortunatly, the two previous ones are a mess. The third one is designed to be extensible, so hopefully it will be the last. */ if( argc > 1 && argv[1][0] == '-' ) { /* Third mode */ int completion_fd = -1; FILE *completion_file; while( 1 ) { static struct option long_options[] = { { "result-fd", required_argument, 0, 'r' } , { "completion-fd", required_argument, 0, 'c' } , { "prefix", required_argument, 0, 'p' } , { "is-quoted", no_argument, 0, 'q' } , { "help", no_argument, 0, 'h' } , { "version", no_argument, 0, 'v' } , { 0, 0, 0, 0 } } ; int opt_index = 0; int opt = getopt_long( argc, argv, GETOPT_STRING, long_options, &opt_index ); if( opt == -1 ) break; switch( opt ) { case 0: { break; } case 'r': { result_fd = get_fd( optarg ); break; } case 'c': { completion_fd = get_fd( optarg ); break; } case 'p': { prefix = str2wcs(optarg); break; } case 'h': { print_help( argv[0], 1 ); exit(0); } case 'v': { debug( 0, L"%ls, version %s\n", program_name, PACKAGE_VERSION ); exit( 0 ); } case 'q': { is_quoted = 1; } } } if( completion_fd == -1 || result_fd == -1 ) { debug( 0, _(L"Unspecified file descriptors") ); exit( 1 ); } if( (completion_file = fdopen( completion_fd, "r" ) ) ) { read_array( completion_file, comp ); fclose( completion_file ); } else { debug( 0, _(L"Could not read completions") ); wperror( L"fdopen" ); exit( 1 ); } if( !prefix ) { prefix = wcsdup( L"" ); } } else { /* Second or first mode. These suck, but we need to support them for backwards compatibility. At least for some time. Third mode was implemented in January 2007, and previous modes should be considered deprecated from that point forward. A reasonable time frame for removal of the code below has yet to be determined. */ if( argc < 3 ) { print_help( argv[0], 1 ); exit( 0 ); } else { mangle_descriptors = 1; prefix = str2wcs( argv[2] ); is_quoted = strcmp( "1", argv[1] )==0; if( argc > 3 ) { /* First mode */ for( i=3; i<argc; i++ ) { wcstring wcs = str2wcstring( argv[i] ); comp.push_back(wcs); } } else { /* Second mode */ read_array( stdin, comp ); } } } // debug( 3, L"prefix is '%ls'", prefix ); init( mangle_descriptors, result_fd ); mangle_descriptions( comp ); if( wcscmp( prefix, L"-" ) == 0 ) join_completions( comp ); std::vector<comp_t *> completions = mangle_completions( comp, prefix ); /** Try to print the completions. Start by trying to print the list in PAGER_MAX_COLS columns, if the completions won't fit, reduce the number of columns by one. Printing a single column never fails. */ for( i = PAGER_MAX_COLS; i>0; i-- ) { switch( completion_try_print( i, prefix, is_quoted, completions ) ) { case PAGER_RETRY: break; case PAGER_DONE: i=0; break; case PAGER_RESIZE: /* This means we got a resize event, so we start over from the beginning. Since it the screen got bigger, we might be able to fit all completions on-screen. */ i=PAGER_MAX_COLS+1; break; } } free(prefix ); fwprintf( out_file, L"%ls", out_buff.c_str() ); if( is_ca_mode ) { writembs(exit_ca_mode); pager_flush(); } destroy(); }
int exec_subshell( const wchar_t *cmd, array_list_t *lst ) { char *begin, *end; char z=0; int prev_subshell = is_subshell; int status, prev_status; io_data_t *io_buffer; const wchar_t *ifs; char sep=0; CHECK( cmd, -1 ); ifs = env_get(L"IFS"); if( ifs && ifs[0] ) { if( ifs[0] < 128 ) { sep = '\n';//ifs[0]; } else { sep = 0; debug( 0, L"Warning - invalid command substitution separator '%lc'. Please change the firsta character of IFS", ifs[0] ); } } is_subshell=1; io_buffer= io_buffer_create( 0 ); prev_status = proc_get_last_status(); if( eval( cmd, io_buffer, SUBST ) ) { status = -1; } else { status = proc_get_last_status(); } io_buffer_read( io_buffer ); proc_set_last_status( prev_status ); is_subshell = prev_subshell; b_append( io_buffer->param2.out_buffer, &z, 1 ); begin=end=io_buffer->param2.out_buffer->buff; if( lst ) { while( 1 ) { if( *end == 0 ) { if( begin != end ) { wchar_t *el = str2wcs( begin ); if( el ) { al_push( lst, el ); } else { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); } } io_buffer_destroy( io_buffer ); return status; } else if( *end == sep ) { wchar_t *el; *end=0; el = str2wcs( begin ); if( el ) { al_push( lst, el ); } else { debug( 2, L"Got null string on line %d of file %s", __LINE__, __FILE__ ); } begin = end+1; } end++; } } io_buffer_destroy( io_buffer ); return status; }
void env_init(const struct config_paths_t *paths /* or NULL */) { char **p; struct passwd *pw; wchar_t *uname; wchar_t *version; /* env_read_only variables can not be altered directly by the user */ const wchar_t * const ro_keys[] = { L"status", L"history", L"version", L"_", L"LINES", L"COLUMNS", L"PWD", L"SHLVL", }; for (size_t i=0; i < sizeof ro_keys / sizeof *ro_keys; i++) { env_read_only.insert(ro_keys[i]); } /* HOME and USER should be writeable by root, since this can be a convenient way to install software. */ if( getuid() != 0 ) { env_read_only.insert(L"HOME"); env_read_only.insert(L"USER"); } /* Names of all dynamically calculated variables */ env_electric.insert(L"history"); env_electric.insert(L"status"); env_electric.insert(L"umask"); top = new env_node_t; global_env = top; global = &top->env; /* Now the environemnt variable handling is set up, the next step is to insert valid data */ /* Import environment variables */ for( p=environ?environ:__environ; p && *p; p++ ) { wchar_t *key, *val; key = str2wcs(*p); if( !key ) { continue; } val = wcschr( key, L'=' ); if( val == 0 ) { env_set( key, L"", ENV_EXPORT ); } else { *val = L'\0'; val++; //fwprintf( stderr, L"Set $%ls to %ls\n", key, val ); if (variable_can_be_array(val)) { for (size_t i=0; val[i] != L'\0'; i++) { if( val[i] == L':' ) { val[i] = ARRAY_SEP; } } } env_set( key, val, ENV_EXPORT | ENV_GLOBAL ); } free(key); } /* Set the given paths in the environment, if we have any */ if (paths != NULL) { env_set(FISH_DATADIR_VAR, paths->data.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_SYSCONFDIR_VAR, paths->sysconf.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_HELPDIR_VAR, paths->doc.c_str(), ENV_GLOBAL | ENV_EXPORT); env_set(FISH_BIN_DIR, paths->bin.c_str(), ENV_GLOBAL | ENV_EXPORT); } /* Set up the PATH variable */ setup_path(); /* Set up the USER variable */ pw = getpwuid( getuid() ); if( pw ) { uname = str2wcs( pw->pw_name ); env_set( L"USER", uname, ENV_GLOBAL | ENV_EXPORT ); free( uname ); } /* Set up the version variable */ version = str2wcs( PACKAGE_VERSION ); env_set( L"version", version, ENV_GLOBAL ); free( version ); const env_var_t fishd_dir_wstr = env_get_string( L"FISHD_SOCKET_DIR"); const env_var_t user_dir_wstr = env_get_string( L"USER" ); wchar_t * fishd_dir = fishd_dir_wstr.missing()?NULL:const_cast<wchar_t*>(fishd_dir_wstr.c_str()); wchar_t * user_dir = user_dir_wstr.missing()?NULL:const_cast<wchar_t*>(user_dir_wstr.c_str()); env_universal_init(fishd_dir , user_dir , &start_fishd, &universal_callback ); /* Set up SHLVL variable */ const env_var_t shlvl_str = env_get_string( L"SHLVL" ); wcstring nshlvl_str = L"1"; if (! shlvl_str.missing()) { long shlvl_i = wcstol(shlvl_str.c_str(), NULL, 10); if (shlvl_i >= 0) { nshlvl_str = format_string(L"%ld", 1 + shlvl_i); } } env_set(L"SHLVL", nshlvl_str.c_str(), ENV_GLOBAL | ENV_EXPORT ); /* Set correct defaults for e.g. USER and HOME variables */ env_set_defaults(); /* Set g_log_forks */ env_var_t log_forks = env_get_string(L"fish_log_forks"); g_log_forks = ! log_forks.missing_or_empty() && from_string<bool>(log_forks); /* Set g_use_posix_spawn. Default to true. */ env_var_t use_posix_spawn = env_get_string(L"fish_use_posix_spawn"); g_use_posix_spawn = (use_posix_spawn.missing_or_empty() ? true : from_string<bool>(use_posix_spawn)); }
// // Label - Draws a label control. // int EZ_label_OnDraw(ez_control_t *self, void *ext_event_info) { int x, y, i = 0; char line[LABEL_LINE_SIZE]; ez_label_t *label = (ez_label_t *)self; int scaled_char_size = label->scaled_char_size; int last_index = -1; int curr_row = 0; int curr_col = 0; clrinfo_t text_color = {RGBA_TO_COLOR(255, 255, 255, 255), 0}; // TODO : Set this in the struct instead. color_t selection_color = RGBA_TO_COLOR(178, 0, 255, 125); color_t caret_color = RGBA_TO_COLOR(255, 0, 0, 125); // Let the super class draw first. EZ_control_OnDraw(self, NULL); // Get the position we're drawing at. EZ_control_GetDrawingPosition(self, &x, &y); // Find any newlines and draw line by line. for (i = 0; i <= label->text_length; i++) { // Draw selection markers. if (label->ext_flags & label_selectable) { if (((label->select_start > -1) && (label->select_end > -1) // Is something selected at all? && (label->select_end != label->select_start)) // Only highlight if we have at least 1 char selected. && (((i >= label->select_start) && (i < label->select_end)) // Is this index selected? || ((i >= label->select_end) && (i < label->select_start))) ) { // If this is one of the selected letters, draw a selection thingie behind it. // TODO : Make this an XOR drawing ontop of the text instead? Draw_AlphaFillRGB( x + (curr_col * scaled_char_size), y + (curr_row * scaled_char_size), scaled_char_size, scaled_char_size, selection_color); } if (i == label->caret_pos.index) { // Draw the caret. Draw_AlphaFillRGB( x + (curr_col * scaled_char_size), y + (curr_row * scaled_char_size), max(5, Q_rint(scaled_char_size * 0.1)), scaled_char_size, caret_color); } } if (i == label->wordwraps[curr_row].index || label->text[i] == '\0') { // We found the end of a line, copy the contents of the line to the line buffer. snprintf(line, min(LABEL_LINE_SIZE, (i - last_index) + 1), "%s", (label->text + last_index + 1)); last_index = i; // Skip the newline character if (label->ext_flags & label_largefont) { Draw_BigString(x, y + (curr_row * scaled_char_size), line, &text_color, 1, label->scale, 1, 0); } else { Draw_SColoredString(x, y + (curr_row * scaled_char_size), str2wcs(line), &text_color, 1, false, label->scale); } curr_row++; curr_col = 0; } else { curr_col++; } } // TODO : Remove this test stuff. { char tmp[1024]; int sublen = abs(label->select_end - label->select_start); if (sublen > 0) { snprintf(tmp, sublen + 1, "%s", label->text + min(label->select_start, label->select_end)); Draw_String(x + (self->width / 2), y + (self->height / 2) + 8, tmp); } } CONTROL_EVENT_HANDLER_CALL(NULL, self, ez_control_t, OnDraw, NULL); return 0; }
wchar *transliterate_char (wchar c) { static wchar s[2] = {0}; if (c == 0x401) return str2wcs("YO"); if (c == 0x404) return str2wcs("E"); if (c == 0x406) return str2wcs("I"); if (c == 0x407) return str2wcs("J"); if (c == 0x40e) return str2wcs("U"); if (c == 0x416) return str2wcs("ZH"); if (c == 0x427) return str2wcs("CH"); if (c == 0x428) return str2wcs("SH"); if (c == 0x429) return str2wcs("SH"); if (c == 0x42e) return str2wcs("YU"); if (c == 0x42f) return str2wcs("YA"); if (c == 0x451) return str2wcs("yo"); if (c == 0x454) return str2wcs("e"); if (c == 0x456) return str2wcs("i"); if (c == 0x457) return str2wcs("j"); if (c == 0x45e) return str2wcs("u"); if (c == 0x436) return str2wcs("zh"); if (c == 0x447) return str2wcs("ch"); if (c == 0x448) return str2wcs("sh"); if (c == 0x449) return str2wcs("sh"); if (c == 0x44e) return str2wcs("yu"); if (c == 0x44f) return str2wcs("ya"); if (c >= 0x0410 && c < 0x0430) s[0] = cyr_trans_table[c - 0x410]; else if (c >= 0x0430 && c < 0x0450) s[0] = tolower(cyr_trans_table[c - 0x430]); else s[0] = '?'; return s; }
wchar *decode_string (const char *s) { static wchar buf[2048]; // should be enough for everyone!!! char encoding[13]; char enc_str[1024]; const char *p, *q, *r; wchar *decoded; int i; buf[0] = 0; p = s; while (1) { p = strstr(p, "=`"); if (!p) break; // copy source string up to p as is qwcslcat (buf, str2wcs(s), min(p-s+qwcslen(buf)+1, sizeof(buf)/sizeof(buf[0]))); s = p; p += 2; // skip the =` for (q = p; isalnum(*q) && q - p < 12; q++) { ; } if (!*q) break; if (*q != ':') { p += 2; continue; } q++; // skip the : assert (q - p <= sizeof(encoding)); strlcpy (encoding, p, q - p); r = strstr(q, "`="); if (!r) { p = q; continue; } strlcpy (enc_str, q, min(r - q + 1, sizeof(enc_str))); for (i = 0; decode_table[i].name; i++) { if (!strcasecmp(encoding, decode_table[i].name)) break; // found it } if (!decode_table[i].name) { // unknown encoding p = r + 2; continue; } decoded = decode_table[i].func(enc_str); qwcslcat (buf, decoded, sizeof(buf)/sizeof(buf[0])); Q_free (decoded); s = p = r + 2; } // copy remainder as is qwcslcat (buf, str2wcs(s), sizeof(buf)/sizeof(buf[0])); return maybe_transliterate(buf); }
VALUE rb_dokan_mount(VALUE self, VALUE mount_point, VALUE dirObj, VALUE fileObj) { ULONG options; PDOKAN_OPTIONS opts; PDOKAN_OPERATIONS ops; rb_require("pathname"); rb_cDirObj = dirObj; rb_cFileObj = fileObj; opts = &dokan.opts; ops = &dokan.ops; options = 0; // TODO: parametrize useful options such as DOKAN_OPTION_NETWORK and DOKAN_OPTION_REMOVABLE opts->Version = DOKAN_VERSION; opts->ThreadCount = 0; // TODO: parametrize this opts->Options = options; opts->GlobalContext = 0; // TODO: fix context work in Dokan driver opts->MountPoint = str2wcs(mount_point); ops->CreateFile = RubyDokan_CreateFile; ops->OpenDirectory = RubyDokan_OpenDirectory; ops->CreateDirectory = RubyDokan_CreateDirectory; ops->Cleanup = RubyDokan_Cleanup; ops->CloseFile = RubyDokan_CloseFile; ops->ReadFile = RubyDokan_ReadFile; ops->WriteFile = RubyDokan_WriteFile; ops->FlushFileBuffers = RubyDokan_FlushFileBuffers; ops->GetFileInformation = RubyDokan_GetFileInformation; ops->FindFiles = RubyDokan_FindFiles; ops->FindFilesWithPattern = RubyDokan_FindFilesWithPattern; ops->SetFileAttributes = RubyDokan_SetFileAttributes; ops->SetFileTime = RubyDokan_SetFileTime; ops->DeleteFile = RubyDokan_DeleteFile; ops->DeleteDirectory = RubyDokan_DeleteDirectory; ops->MoveFile = RubyDokan_MoveFile; ops->SetEndOfFile = RubyDokan_SetEndOfFile; ops->SetAllocationSize = RubyDokan_SetAllocationSize; ops->LockFile = RubyDokan_LockFile; ops->UnlockFile = RubyDokan_UnlockFile; ops->GetDiskFreeSpace = RubyDokan_GetDiskFreeSpace; ops->GetVolumeInformation = RubyDokan_GetVolumeInformation; ops->Unmount = RubyDokan_Unmount; ops->GetFileSecurity = RubyDokan_GetFileSecurity; ops->SetFileSecurity = RubyDokan_SetFileSecurity; dokan.thStartEvent = CreateEvent(NULL, FALSE, FALSE, "DokanThreadStartEvent"); dokan.thread = CreateThread ( NULL, 0, (LPTHREAD_START_ROUTINE)th_dokan_mainloop, NULL, 0, NULL ); WaitForSingleObject(dokan.thStartEvent, INFINITE); dokan_dispatcher_run(); return Qnil; }
int main( int argc, char **argv ) { struct stat tmp; int res=1; const char *cmd=0; int my_optind=0; set_main_thread(); setup_fork_guards(); wsetlocale( LC_ALL, L"" ); is_interactive_session=1; program_name=L"fish"; stat("----------FISH_HIT_MAIN----------", &tmp); my_optind = fish_parse_opt( argc, argv, &cmd ); /* No-exec is prohibited when in interactive mode */ if( is_interactive_session && no_exec) { debug( 1, _(L"Can not use the no-execute mode when running an interactive session") ); no_exec = 0; } const struct config_paths_t paths = determine_config_directory_paths(argv[0]); proc_init(); event_init(); wutil_init(); //parser_init(); builtin_init(); function_init(); env_init(&paths); reader_init(); history_init(); parser_t &parser = parser_t::principal_parser(); if (g_log_forks) printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); if( read_init(paths) ) { if( cmd != 0 ) { wchar_t *cmd_wcs = str2wcs( cmd ); res = parser.eval( cmd_wcs, 0, TOP ); free(cmd_wcs); reader_exit(0, 0); } else { if( my_optind == argc ) { res = reader_read( STDIN_FILENO, 0 ); } else { char **ptr; char *file = *(argv+(my_optind++)); int i; int fd; wchar_t *rel_filename, *abs_filename; if( ( fd = open(file, O_RDONLY) ) == -1 ) { wperror( L"open" ); return 1; } // OK to not do this atomically since we cannot have gone multithreaded yet set_cloexec(fd); if( *(argv+my_optind)) { wcstring sb; for( i=1,ptr = argv+my_optind; *ptr; i++, ptr++ ) { if( i != 1 ) sb.append( ARRAY_SEP_STR ); sb.append( str2wcstring( *ptr )); } env_set( L"argv", sb.c_str(), 0 ); } rel_filename = str2wcs( file ); abs_filename = wrealpath( rel_filename, 0 ); if( !abs_filename ) { abs_filename = wcsdup(rel_filename); } reader_push_current_filename( intern( abs_filename ) ); free( rel_filename ); free( abs_filename ); res = reader_read( fd, 0 ); if( res ) { debug( 1, _(L"Error while reading file %ls\n"), reader_current_filename()?reader_current_filename(): _(L"Standard input") ); } reader_pop_current_filename(); } } } proc_fire_event( L"PROCESS_EXIT", EVENT_EXIT, getpid(), res ); history_destroy(); proc_destroy(); builtin_destroy(); reader_destroy(); parser.destroy(); wutil_destroy(); event_destroy(); env_destroy(); if (g_log_forks) printf("%d: g_fork_count: %d\n", __LINE__, g_fork_count); return res?STATUS_UNKNOWN_COMMAND:proc_get_last_status(); }
/** Test wide/narrow conversion by creating random strings and verifying that the original string comes back thorugh double conversion. */ static void test_convert() { /* char o[] = { -17, -128, -121, -68, 0 } ; wchar_t *w = str2wcs(o); char *n = wcs2str(w); int i; for( i=0; o[i]; i++ ) { bitprint(o[i]);; //wprintf(L"%d ", o[i]); } wprintf(L"\n"); for( i=0; w[i]; i++ ) { wbitprint(w[i]);; //wprintf(L"%d ", w[i]); } wprintf(L"\n"); for( i=0; n[i]; i++ ) { bitprint(n[i]);; //wprintf(L"%d ", n[i]); } wprintf(L"\n"); return; */ int i; buffer_t sb; say( L"Testing wide/narrow string conversion" ); b_init( &sb ); for( i=0; i<ESCAPE_TEST_COUNT; i++ ) { wchar_t *w; char *o, *n; char c; sb.used=0; while( rand() % ESCAPE_TEST_LENGTH ) { c = rand (); b_append( &sb, &c, 1 ); } c = 0; b_append( &sb, &c, 1 ); o = (char *)sb.buff; w = str2wcs(o); n = wcs2str(w); if( !o || !w || !n ) { err( L"Conversion cycle of string %s produced null pointer on %s", o, w?L"str2wcs":L"wcs2str" ); } if( strcmp(o, n) ) { err( L"%d: Conversion cycle of string %s produced different string %s", i, o, n ); } free( w ); free( n ); } }