/* Return pointer to copy of shell command in the command buffer */ static const char * get_shell_command( const char ** const ibufpp ) { static char * buf = 0; static int bufsz = 0; static char * shcmd = 0; /* shell command buffer */ static int shcmdsz = 0; /* shell command buffer size */ static int shcmdlen = 0; /* shell command length */ const char * p; /* substitution char pointer */ int i = 0, len; if( restricted() ) { set_error_msg( "Shell access restricted" ); return 0; } if( !get_extended_line( ibufpp, &len, true ) ) return 0; p = *ibufpp; if( !resize_buffer( &buf, &bufsz, len + 1 ) ) return 0; buf[i++] = '!'; /* prefix command w/ bang */ while( **ibufpp != '\n' ) { if( **ibufpp == '!' ) { if( p != *ibufpp ) { if( !resize_buffer( &buf, &bufsz, i + 1 ) ) return 0; buf[i++] = *(*ibufpp)++; } else if( !shcmd || ( traditional() && !*( shcmd + 1 ) ) ) { set_error_msg( "No previous command" ); return 0; } else { if( !resize_buffer( &buf, &bufsz, i + shcmdlen ) ) return 0; for( p = shcmd + 1; p < shcmd + shcmdlen; ) buf[i++] = *p++; p = (*ibufpp)++; } } else if( **ibufpp == '%' ) { if( !def_filename[0] ) { set_error_msg( "No current filename" ); return 0; } p = strip_escapes( def_filename ); len = strlen( p ); if( !resize_buffer( &buf, &bufsz, i + len ) ) return 0; while( len-- ) buf[i++] = *p++; p = (*ibufpp)++; } else { if( !resize_buffer( &buf, &bufsz, i + 2 ) ) return 0; buf[i++] = **ibufpp; if( *(*ibufpp)++ == '\\' ) buf[i++] = *(*ibufpp)++; } } while( **ibufpp == '\n' ) ++*ibufpp; /* skip newline */ if( !resize_buffer( &shcmd, &shcmdsz, i + 1 ) ) return 0; memcpy( shcmd, buf, i ); shcmdlen = i; shcmd[i] = 0; if( *p == '!' || *p == '%' ) printf( "%s\n", shcmd + 1 ); return shcmd; }
static GList *add_result(GList *results, cb_object *capo, char *url, char *summary, char *release) { if(levenshtein_strnormcmp(capo->s, capo->s->album, release) <= capo->s->fuzzyness) { if(strlen(summary) >= 125) { GlyrMemCache *result = DL_init(); result->data = g_strdup_printf("%s\n \n \nRead more on: %s\n", summary, url); result->size = strlen(result->data); result->size -= strip_escapes(result->data, result->size); return g_list_prepend(results, result); } } return results; }
/* write_file: write a range of lines to a named file/pipe; return line count */ long write_file(char *fn, const char *mode, long n, long m) { FILE *fp; long size; fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode); if (fp == NULL) { fprintf(stderr, "%s: %s\n", fn, strerror(errno)); errmsg = "cannot open output file"; return ERR; } else if ((size = write_stream(fp, n, m)) < 0) return ERR; else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { fprintf(stderr, "%s: %s\n", fn, strerror(errno)); errmsg = "cannot close output file"; return ERR; } fprintf(stdout, !scripted ? "%lu\n" : "", size); return n ? m - n + 1 : 0; }
/* write_file: write a range of lines to a named file/pipe; return line count */ int write_file(char *fn, char *mode, int n, int m) { FILE *fp; int size; fp = (*fn == '!') ? popen(fn+1, "w") : fopen(strip_escapes(fn), mode); if (fp == NULL) { perror(fn); seterrmsg("cannot open output file"); return ERR; } else if ((size = write_stream(fp, n, m)) < 0) return ERR; else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { perror(fn); seterrmsg("cannot close output file"); return ERR; } fprintf(stderr, !scripted ? "%d\n" : "", size); return n ? m - n + 1 : 0; }
/* read_file: read a named file/pipe into the buffer; return line count */ long read_file(char *fn, long n) { FILE *fp; long size; fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r"); if (fp == NULL) { fprintf(stderr, "%s: %s\n", fn, strerror(errno)); errmsg = "cannot open input file"; return ERR; } else if ((size = read_stream(fp, n)) < 0) return ERR; else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { fprintf(stderr, "%s: %s\n", fn, strerror(errno)); errmsg = "cannot close input file"; return ERR; } fprintf(stdout, !scripted ? "%lu\n" : "", size); return current_addr - n; }
/* read_file: read a named file/pipe into the buffer; return line count */ int read_file(char *fn, int n) { FILE *fp; int size; fp = (*fn == '!') ? popen(fn + 1, "r") : fopen(strip_escapes(fn), "r"); if (fp == NULL) { perror(fn); seterrmsg("cannot open input file"); return ERR; } else if ((size = read_stream(fp, n)) < 0) return ERR; else if (((*fn == '!') ? pclose(fp) : fclose(fp)) < 0) { perror(fn); seterrmsg("cannot close input file"); return ERR; } fprintf(stderr, !scripted ? "%d\n" : "", size); return current_addr - n; }
/* execute the next command in command buffer; return error status */ static int exec_command( const char ** const ibufpp, const int prev_status, const bool isglobal ) { const char * fnp; int gflags = 0; int addr, c, n; const int addr_cnt = extract_addr_range( ibufpp ); if( addr_cnt < 0 ) return ERR; *ibufpp = skip_blanks( *ibufpp ); c = *(*ibufpp)++; switch( c ) { case 'a': if( !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !append_lines( ibufpp, second_addr, isglobal ) ) return ERR; break; case 'c': if( first_addr == 0 ) first_addr = 1; if( second_addr == 0 ) second_addr = 1; if( !check_current_addr( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !delete_lines( first_addr, second_addr, isglobal ) || !append_lines( ibufpp, current_addr(), isglobal ) ) return ERR; break; case 'd': if( !check_current_addr( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !delete_lines( first_addr, second_addr, isglobal ) ) return ERR; inc_current_addr(); break; case 'e': if( modified() && !scripted() && prev_status != EMOD ) return EMOD; /* fall through */ case 'E': if( unexpected_address( addr_cnt ) || unexpected_command_suffix( **ibufpp ) ) return ERR; fnp = get_filename( ibufpp ); if( !fnp || !delete_lines( 1, last_addr(), isglobal ) || !close_sbuf() ) return ERR; if( !open_sbuf() ) return FATAL; if( fnp[0] && fnp[0] != '!' ) set_def_filename( fnp ); if( traditional() && !fnp[0] && !def_filename[0] ) { set_error_msg( "No current filename" ); return ERR; } if( read_file( fnp[0] ? fnp : def_filename, 0 ) < 0 ) return ERR; reset_undo_state(); set_modified( false ); break; case 'f': if( unexpected_address( addr_cnt ) || unexpected_command_suffix( **ibufpp ) ) return ERR; fnp = get_filename( ibufpp ); if( !fnp ) return ERR; if( fnp[0] == '!' ) { set_error_msg( "Invalid redirection" ); return ERR; } if( fnp[0] ) set_def_filename( fnp ); printf( "%s\n", strip_escapes( def_filename ) ); break; case 'g': case 'v': case 'G': case 'V': if( isglobal ) { set_error_msg( "Cannot nest global commands" ); return ERR; } n = ( c == 'g' || c == 'G' ); /* mark matching lines */ if( !check_addr_range( 1, last_addr(), addr_cnt ) || !build_active_list( ibufpp, first_addr, second_addr, n ) ) return ERR; n = ( c == 'G' || c == 'V' ); /* interactive */ if( ( n && !get_command_suffix( ibufpp, &gflags ) ) || !exec_global( ibufpp, gflags, n ) ) return ERR; break; case 'h': case 'H': if( unexpected_address( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( c == 'H' ) verbose = !verbose; if( ( c == 'h' || verbose ) && errmsg[0] ) fprintf( stderr, "%s\n", errmsg ); break; case 'i': if( second_addr == 0 ) second_addr = 1; if( !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !append_lines( ibufpp, second_addr - 1, isglobal ) ) return ERR; break; case 'j': if( !check_addr_range( current_addr(), current_addr() + 1, addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( first_addr != second_addr && !join_lines( first_addr, second_addr, isglobal ) ) return ERR; break; case 'k': n = *(*ibufpp)++; if( second_addr == 0 ) { invalid_address(); return ERR; } if( !get_command_suffix( ibufpp, &gflags ) || !mark_line_node( search_line_node( second_addr ), n ) ) return ERR; break; case 'l': case 'n': case 'p': if( c == 'l' ) n = GLS; else if( c == 'n' ) n = GNP; else n = GPR; if( !check_current_addr( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) || !display_lines( first_addr, second_addr, gflags | n ) ) return ERR; gflags = 0; break; case 'm': if( !check_current_addr( addr_cnt ) || !get_third_addr( ibufpp, &addr ) ) return ERR; if( addr >= first_addr && addr < second_addr ) { set_error_msg( "Invalid destination" ); return ERR; } if( !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !move_lines( first_addr, second_addr, addr, isglobal ) ) return ERR; break; case 'P': case 'q': case 'Q': if( unexpected_address( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( c == 'P' ) prompt_on = !prompt_on; else if( modified() && !scripted() && c == 'q' && prev_status != EMOD ) return EMOD; else return QUIT; break; case 'r': if( unexpected_command_suffix( **ibufpp ) ) return ERR; if( addr_cnt == 0 ) second_addr = last_addr(); fnp = get_filename( ibufpp ); if( !fnp ) return ERR; if( !isglobal ) clear_undo_stack(); if( !def_filename[0] && fnp[0] != '!' ) set_def_filename( fnp ); if( traditional() && !fnp[0] && !def_filename[0] ) { set_error_msg( "No current filename" ); return ERR; } addr = read_file( fnp[0] ? fnp : def_filename, second_addr ); if( addr < 0 ) return ERR; if( addr ) set_modified( true ); break; case 's': if( !command_s( ibufpp, &gflags, addr_cnt, isglobal ) ) return ERR; break; case 't': if( !check_current_addr( addr_cnt ) || !get_third_addr( ibufpp, &addr ) || !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !copy_lines( first_addr, second_addr, addr ) ) return ERR; break; case 'u': if( unexpected_address( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) || !undo( isglobal ) ) return ERR; break; case 'w': case 'W': n = **ibufpp; if( n == 'q' || n == 'Q' ) ++*ibufpp; if( unexpected_command_suffix( **ibufpp ) ) return ERR; fnp = get_filename( ibufpp ); if( !fnp ) return ERR; if( addr_cnt == 0 && last_addr() == 0 ) first_addr = second_addr = 0; else if( !check_addr_range( 1, last_addr(), addr_cnt ) ) return ERR; if( !def_filename[0] && fnp[0] != '!' ) set_def_filename( fnp ); if( traditional() && !fnp[0] && !def_filename[0] ) { set_error_msg( "No current filename" ); return ERR; } addr = write_file( fnp[0] ? fnp : def_filename, ( c == 'W' ) ? "a" : "w", first_addr, second_addr ); if( addr < 0 ) return ERR; if( addr == last_addr() ) set_modified( false ); else if( modified() && !scripted() && n == 'q' && prev_status != EMOD ) return EMOD; if( n == 'q' || n == 'Q' ) return QUIT; break; case 'x': if( second_addr < 0 || last_addr() < second_addr ) { invalid_address(); return ERR; } if( !get_command_suffix( ibufpp, &gflags ) ) return ERR; if( !isglobal ) clear_undo_stack(); if( !put_lines( second_addr ) ) return ERR; break; case 'y': if( !check_current_addr( addr_cnt ) || !get_command_suffix( ibufpp, &gflags ) || !yank_lines( first_addr, second_addr ) ) return ERR; break; case 'z': first_addr = 1; if( !check_addr_range( first_addr, current_addr() + ( traditional() || !isglobal ), addr_cnt ) ) return ERR; if( **ibufpp > '0' && **ibufpp <= '9' ) { if( parse_int( &n, *ibufpp, ibufpp ) ) set_window_lines( n ); else return ERR; } if( !get_command_suffix( ibufpp, &gflags ) || !display_lines( second_addr, min( last_addr(), second_addr + window_lines() ), gflags ) ) return ERR; gflags = 0; break; case '=': if( !get_command_suffix( ibufpp, &gflags ) ) return ERR; printf( "%d\n", addr_cnt ? second_addr : last_addr() ); break; case '!': if( unexpected_address( addr_cnt ) ) return ERR; fnp = get_shell_command( ibufpp ); if( !fnp ) return ERR; if( system( fnp + 1 ) < 0 ) { set_error_msg( "Can't create shell process" ); return ERR; } if( !scripted() ) printf( "!\n" ); break; case '\n': first_addr = 1; if( !check_addr_range( first_addr, current_addr() + ( traditional() || !isglobal ), addr_cnt ) || !display_lines( second_addr, second_addr, 0 ) ) return ERR; break; case '#': while( *(*ibufpp)++ != '\n' ) ; break; default : set_error_msg( "Unknown command" ); return ERR; } if( gflags && !display_lines( current_addr(), current_addr(), gflags ) ) return ERR; return 0; }