I've just installed DEBIAN today and installed XXXXX application.
This application create ~/.XXXXX/ folder configuration.
I find that the ~/.XXXXX folder is owned by root. Applying any change for instance, then closing and reopening XXXXX, should reflect the applied change.
However, any channel or setting change is forgotten immediately.
A simple chown command solves all.
I was a little confused to start with when I couldn't save my settings... but a little digging shows the problem. It's a little annoying, and the only additional application I've installed so far which behaves this way, which kinda singles it out.
Because this application not have maintainer, I want to resolve this problem for another users.
I beleve that the proble is in debian/postinst file:
set -e
setuid () {
db_get XXXXX/setuid
if [ -x /usr/bin/XXXXX ] && [ "$RET" = "false" ] ; then
if [ ! -x /usr/sbin/dpkg-statoverride ] ||\
! /usr/sbin/dpkg-statoverride --list /usr/bin/XXXXX >/dev/null; then
chown root:root /usr/bin/XXXXX
chmod u=rwx,go=rx /usr/bin/XXXXX
fi
else
if [ ! -x /usr/sbin/dpkg-statoverride ] || \
! /usr/sbin/dpkg-statoverride --list /usr/bin/XXXXX >/dev/null; then
chown root:root /usr/bin/XXXXX
chmod u=rwxs,go=rx /usr/bin/XXXXX
fi
fi
}
# Parse the option requested from XXXXX-configure
get_option () {
OPTION=`XXXXX-configure --$1 2>/dev/null | awk -F: '{ print \$2 }'`
}
suck_XXXXX_xml () {
# If XXXXX-configure was not there at Debconf, but
# /etc/XXXXX/XXXXX.xml was, then we presume that the
# administrator knew what he was doing. We will therefore suck
# this information into the Debconf database now that
# XXXXX-configure is installed.
if [ -f /etc/XXXXX/debconf.XXXXX.xml ]; then
get_option norm
db_set XXXXX/norm "$OPTION"
get_option frequencies
db_set XXXXX/frequencies-ntsc "$OPTION"
db_set XXXXX/frequencies-jp "$OPTION"
db_set XXXXX/frequencies-pal "$OPTION"
get_option device
db_set XXXXX/v4ldevice "$OPTION"
get_option vbidevice
db_set XXXXX/vbidevice "$OPTION"
get_option priority
db_set XXXXX/processpriority "$OPTION"
fi
}
### MAIN POSTINST ###
case "$1" in
configure)
# Load Debconf library
. /usr/share/debconf/confmodule
# Handle the setuid bit.
setuid
# Load /etc/XXXXX/XXXXX.xml into Debconf, if necessary
suck_XXXXX_xml
# Try to set the /var/run/XXXXX directory to video group
if [ -d /var/run/XXXXX ] ; then
if [ ! -x /usr/sbin/dpkg-statoverride ] || \
! /usr/sbin/dpkg-statoverride --list /var/run/XXXXX >/dev/null; then
chmod ug=rwx,o=rxt /var/run/XXXXX
chown root:video /var/run/XXXXX
fi
fi
CONFIGFILE=/etc/XXXXX/XXXXX.xml
db_get XXXXX/norm
NORM=$RET
case "$NORM" in
NTSC|PAL-M|PAL-Nc)
db_get XXXXX/frequencies-ntsc
case "$RET" in
Cable) FREQTABLE=us-cable ;;
Broadcast) FREQTABLE=us-broadcast ;;
*) FREQTABLE=us-cable100 ;;
esac
;;
NTSC-JP)
db_get XXXXX/frequencies-jp
case "$RET" in
Cable) FREQTABLE=japan-cable ;;
*) FREQTABLE=japan-broadcast ;;
esac
;;
PAL|PAL-60|PAL-N|SECAM)
db_get XXXXX/frequencies-pal
case "$RET" in
Europe) FREQTABLE=europe ;;
France) FREQTABLE=france ;;
Russia) FREQTABLE=russia ;;
Australia) FREQTABLE=australia ;;
"New Zealand") FREQTABLE=newzealand ;;
"China Broadcast") FREQTABLE=china-broadcast ;;
"Australia Optus cable") FREQTABLE=australia-optus ;;
*) FREQTABLE=custom ;;
esac
;;
*)
FREQTABLE=custom
;;
esac
db_get XXXXX/v4ldevice
V4LDEV=$RET
db_get XXXXX/vbidevice
VBIDEV=$RET
db_get XXXXX/processpriority
PRI=$RET
db_stop
# Create the configuration file if it doesn't exist
if [ ! -f $CONFIGFILE ]; then
cp /usr/share/doc/XXXXX/examples/default.XXXXX.xml $CONFIGFILE
fi
# Configure XXXXX.
XXXXX-configure --configfile="$CONFIGFILE" --norm="$NORM" \
--frequencies="$FREQTABLE" --device="$V4LDEV" \
--vbidevice="$VBIDEV" --priority="$PRI" 2>/dev/null
;;
abort-upgrade|abort-remove|abort-deconfigure)
;;
*)
echo "postinst called with unknown argument \`$1'" >&2
exit 1
;;
esac
Any help is welcome,
Regards.
From app code
int mkdir_and_force_owner( const char *path, uid_t uid, gid_t gid )
{
if( mkdir( path, S_IRWXU ) < 0 ) {
if( errno != EEXIST ) {
lfprintf( stderr, _("Cannot create %s: %s\n"),
path, strerror( errno ) );
} else {
/* It exists, make sure it's a directory. */
DIR *temp_dir = opendir( path );
if( !path ) {
lfprintf( stderr, _("Cannot open %s: %s\n"),
path, strerror( errno ) );
} else {
closedir( temp_dir );
return 1;
}
}
} else {
/* We created the directory, now force it to be owned by the user. */
if( chown( path, uid, gid ) < 0 ) {
lfprintf( stderr, _("Cannot change owner of %s: %s.\n"),
path, strerror( errno ) );
} else {
return 1;
}
}
return 0;
}
ct->uid = getuid();
/* Make the ~/.XXXXX directory every time on startup, to be safe. */
if( asprintf( &temp_dirname, "%s/.XXXXX", getenv( "HOME" ) ) < 0 ) {
/* FIXME: Clean up ?? */
return 0;
}
mkdir_and_force_owner( temp_dirname, ct->uid, getgid() );
free( temp_dirname );
This is main app with create initial directory in home. Drop root privileges as early as possible. Only re-enable them to get access to the real-time scheduler. This not work in debian.
int main( int argc, char **argv )
{
rtctimer_t *rtctimer = 0;
int read_stdin = 1;
int result = 0;
int realtime = 0;
uid_t priv_uid = geteuid();
uid_t user_uid = getuid();
/*
* Temporarily drop down to user-level access, so that files aren't
* created setuid root.
*/
if( seteuid( user_uid ) == -1 ) {
lfprintf( stderr, _("\n"
" Failed to drop root privileges: %s.\n"
" motv will now exit to avoid security problems.\n\n"),
strerror( errno ) );
return 1;
}
setup_i18n();
setup_utf8();
lfprintf( stderr, _("Running %s.\n"), PACKAGE_STRING );
/* Steal system resources in the name of performance. */
/* Get maximum priority before dropping root privileges. We'll drop back */
/* to the value specified in the config file (or the default) later. */
seteuid( priv_uid );
setpriority( PRIO_PROCESS, 0, -19 );
if( set_realtime_priority( 0 ) ) {
realtime = 1;
}
rtctimer = rtctimer_new( 0 );
if( rtctimer ) {
if( !rtctimer_set_interval( rtctimer, 1024 ) &&
!rtctimer_set_interval( rtctimer, 64 ) ) {
rtctimer_delete( rtctimer );
rtctimer = 0;
} else {
rtctimer_start_clock( rtctimer );
if( rtctimer_get_resolution( rtctimer ) < 1024 ) {
rtctimer_delete( rtctimer );
rtctimer = 0;
}
}
}
/* We've now stolen all our root-requiring resources, drop to a user. */
if( setuid( user_uid ) == -1 ) {
/*
* This used to say "Unknown problems", but we're printing an
* error string, so that didn't really make sense, did it?
*/
lfprintf( stderr, _("\n"
" Failed to drop root privileges: %s.\n"
" motv will now exit to avoid security problems.\n\n"),
strerror( errno ) );
return 1;
}
/* Ditch stdin early. */
if( isatty( STDIN_FILENO ) ) {
read_stdin = 0;
close( STDIN_FILENO );
}
/* Run motv. */
for(;;) {
if( result == 2 ) {
char *new_argv[ 2 ];
new_argv[ 0 ] = "motv";
new_argv[ 1 ] = 0;
result = motv_main( rtctimer, read_stdin, realtime, 0, new_argv );
} else {
result = motv_main( rtctimer, read_stdin, realtime, argc, argv );
}
if( result != 2 ) break;
}
if( rtctimer ) {
rtctimer_delete( rtctimer );
}
return result;
}
The problem is not created by the debian package postinst script because it never creates the ~/.XXXXX directory.
Check the values of ct->uid and getgid() when you call mkdir_and_force_owner(): that function is not called on your main() so I cannot read how you are calling it.
You have to be sure that they are not 0 and 0: print the values for debug. In this case the function will create and chown() the dir root:root; BTW you are running the software as root due to the setuid bit, otherwise you couldn't chown() your configuration dir.
Related
In Linux Ubuntu 20.04.4, I implemented a simple shell command in the "sh.c" file.
Entering
./a.out
and command line by line runs normally.
enter image description here
ls > y
cat < y | sort | uniq | wc > y1
cat y1
rm y1
ls | sort | uniq | wc
rm y
However, if you save the commands to the "t.sh" file
enter image description here
and run them at once like
./a.out < t.sh
an error appears.
enter image description here
print result :
5 5 29
5 5 29
cat: y1: No such file or directory
rm: Cannot erase 'y1': no such file or directory
4 4 27
rm: Cannot clear 'y': no such file or directory
When I checked with the "ls" command, both the cat and rm commands worked well, but I got a error message like that "rm: Cannot erase 'y1': no such file or directory."
What's the problem?
The other person worked normally with the same code...
This is part of the code implemented.
void runcmd(struct cmd *cmd)
{
int p[2], r;
int fd;
int pid;
char str[30] ="/bin/";
FILE * stream;
struct execcmd *ecmd;
struct pipecmd *pcmd;
struct redircmd *rcmd;
if(cmd == 0)
_exit(0);
switch(cmd->type){
default:
fprintf(stderr, "unknown runcmd\n");
_exit(-1);
case ' ':
ecmd = (struct execcmd*)cmd;
if(ecmd->argv[0] == 0){
_exit(0);
fprintf(stderr, "exec not implemented\n");
}
// Your code here ...
else if(execvp(ecmd->argv[0],ecmd->argv)==-1){
ecmd->argv[0] = strcat(str,ecmd->argv[0]);
if(execvp(ecmd->argv[0],ecmd->argv)==-1){
fprintf(stderr,"file not found\n");
exit(1);
}
}
break;
case '>':
rcmd = (struct redircmd*)cmd;
ecmd = (struct execcmd*)(rcmd->cmd);
if(0 <(fd = open(rcmd->file,O_CREAT|O_WRONLY,0644))){
stream = freopen(rcmd->file,"w",stdout);
runcmd(rcmd->cmd);
fclose(stream);
}
else {
fprintf(stderr,"file open error\n");
}
close(fd);
stream = NULL;
break;
case '<':
rcmd = (struct redircmd*)cmd;
// Your code here ...
if( 0 < (fd = open(rcmd->file,rcmd->flags))){
stream = freopen(rcmd->file,"r",stdin);
runcmd(rcmd->cmd);
fclose(stream);
close(fd);
}
else fprintf(stderr,"file open error\n");
break;
case '|':
pcmd = (struct pipecmd*)cmd;
// Your code here ...
struct cmd * lcmd =(pcmd->left);
struct cmd * rcmd =(pcmd->right);
int fd[2];
if(pipe(fd)==-1){
fprintf(stderr,"pipe error");
exit(1);
}
pid = fork1();
if(pid == 0){
dup2(fd[1],1);
close(fd[0]);
runcmd(lcmd);
}
else{
dup2(fd[0],0);
close(fd[1]);
runcmd(rcmd);
}
break;
}
_exit(0);
}
Have you declared #!/bin/sh at top of script
i am using tput sc/rc/ed and printf '\E[n<A|B|C|D>'|printf '\E[y;xH',here two ex:
tty_esc(){ printf "\e[%s" "$1"; }
tty_cursor_locate(){ tty_esc "${2};${1}H"; }
tty_cursor_right(){ tty_esc ${1}C; }
print_center()
{
local _width=$(tput cols)
local _str=$1
local _row=$2
local _cols=$((((${_width} - ${#_str})) / 2))
tty_cursor_locate ${_cols:-100} ${_row:-1}
printf "%s\n" " ${_str} "
}
show_net_adapter()
{
local _addr _iface _count
local _origin=$1
iface_line_count=
tty_cursor_locate ${_origin:-0} 4
printf "%s\n" "Current connected adapter(s):"
for _iface in $(get_net_adapter);do
if [[ "${_iface}" != "lo" ]];then
_addr=$(get_net_addr ${_iface})
test -z "${_addr}" && continue
let _count+=1
let iface_line_count+=1
if [[ ${_count} != 1 ]];then
unset _count
printf '%s' "${tty_rever}"
fi
tty_cursor_right ${_origin:-0}
print_fill 50 ${_iface} ${_addr:--}
printf "${tty_reset}"
fi
done
print_line -s "=" ${line_origin}
}
as above, I should locate the cursor before I print something.
BTW
I use trap "myfunc" WINCH, it only works once. when I try again to change my crt. size, it doesn't work.
Not really sure what you mean by in default position always, either intentations or overwrite the text but the following function can do both.
#!/bin/sh
preent () { # $1=indent start line, $2=spaces, $3=reset cursor, $4=update (1=itself, 2=delete previous lines, 0=newline), $5=save cursor, $6=text
if text="$6""$7""$8""$9""${10}" awk -v col="$COLUMNS" -v cp="$_CURSOR_POS" -v id="$1" -v spc="$2" -v rc="$3" -v u="$4" -v sc="$5" '
BEGIN { t=ENVIRON["text"]; lt=sprintf("%d",col/4); idx=1; len=length(t); y=0; sp=sprintf("% " spc "s",""); delete A;
for(ln=1;idx<len;ln++) { if(ln==id) { col=col-spc; y=1 } bd=col-lt; f=0
for(i=idx+col-1;i>bd;i--) { c=substr(t,i,1);
if(c==" ") {
if(y) { A[ln]=sprintf("%s%s",sp,substr(t,idx,i-idx)); idx=i+1; f=1; break
} else { A[ln]=substr(t,idx,i-idx); idx=i+1; f=1; break }
} else if(c=="") {
if(y) { A[ln]=sprintf("%s%s",sp,substr(t,idx,i-idx)); idx=i; f=1; break
} else { A[ln]=substr(t,idx,i-idx); idx=i; f=1; break; }
}
}
if(!f) {
if(y) { A[ln]=sprintf("%s%s",sp,substr(t,idx,col)); idx=idx+col
} else { A[ln]=substr(t,idx,col); idx=idx+col }
}
} if(rc=="true") cp=0;
if(u=="1") { for(i=1;i<ln;i++) printf("\x1B[1A\x1B[K"); cp=cp+1-i
} else if(u=="2") { for(i=0;i<cp;i++) printf("\x1B[1A\x1B[K"); cp=0 }
for(i=1;i<ln;i++) printf("%s\n",A[i]);
if(sc=="true") { exit ln-1+cp } else { exit 0 }
}'; then _CURSOR_POS="$?"; else _CURSOR_POS="$?"; fi
}
Example 1 (Long text, 5 spaces indent, indent starts from 2nd line)
preent 2 5 'false' 0 'false' 'You never say good-bye Handong-an monghani udukoni anja Dashi saenggakhatjiman ' \
'Momchul sun optkesso Ontong kudae saenggak hal subakke omnun ' \
"Nae jashini miwo Don't you let me go Baby don't you let me down"
Output
You never say good-bye Handong-an monghani
udukoni anja Dashi saenggakhatjiman Momchul
sun optkesso Ontong kudae saenggak hal
subakke omnun Nae jashini miwo Don't you
let me go Baby don't you let me down
Example 2 (Long text with no spaces)
preent 2 5 'false' 0 'false' 'Youneversaygood-byeHandong-anmonghaniudukonianjaDashisaenggakhatjiman' \
'MomchulsunoptkessoOntongkudaesaenggakhalsubakkeomnun' \
"NaejashinimiwoDon'tyouletmegoBabydon'tyouletmedown"
Output
Youneversaygood-byeHandong-anmonghaniudukonianjaD
ashisaenggakhatjimanMomchulsunoptkessoOntong
kudaesaenggakhalsubakkeomnunNaejashinimiwoDo
n'tyouletmegoBabydon'tyouletmedown
I am trying to execute the open source code which finds the list of tables involved in SQL.
I am working on Retrieve table names from Oracle queries.
I understood the expressions and commands to some extent and tried it.
Details of my execution:
GetTable.pl file
same as in the link
test.sql file
I didn't use the one in link. Instead I had only a single SQL for testing.
SELECT emp_name FROM load_tables.temp;
Executed in Strawberry Perl
I tried the following
$ perl GetTable.pl
Usage : GetTable <sql query file>
$ perl test.sql
Can't locate object method "FROM" via package "load_tables" (perhaps you forgot to load "load_tables"?) at test.sql line 1
Can someone help me in executing it? I'm not sure if there is problem with code as I could see two people have executed successfully.
Perl code
#!/usr/bin/perl
use warnings;
#Function which gets the table names and formats and prints them.
sub printTable {
my $tab = shift;
$tab =~ s/,\s+/,/g;
$tab =~ s/\s+,/,/g;
my #out = split( /,/, $tab );
foreach ( #out ) {
$_ =~ s/ .*//;
print $opr, $_, "\n";
}
}
# Function which gets the indivdual queries and separtes the table
# names from the queries. Sub-Queries, co-related queries, etc..
# will also be handled.
sub process {
local $opr;
my $line = shift;
$line =~ s/\n/ /g;
if ( $line =~ m/^\s*(select|delete)/i ) {
if ( $line =~ m/^\s*select/i ) {
$opr = "SELECT: ";
}
else {
$opr = "DELETE: ";
}
if ( $line =~ m/from.*where/i ) {
while ( $line =~ m/from\s+(.*?)where/ig ) {
&printTable( $1 );
}
}
elsif ( $line =~ m/from.*;/i ) {
while ( $line =~ m/from\s+(.*);/ig ) {
&printTable( $1 );
}
}
}
elsif ( $line =~ m/^\s*update\s+(\w+)\s+/i ) {
$opr = "UPDATE: ";
&printTable( $1 );
}
elsif ( $line =~ m/^\s*insert\s+into\s+(\w+)\s+/i ) {
$opr = "INSERT: ";
&printTable( $1 );
}
}
#The main function which reads the files and reads the
#query into a variable and sends it to process function.
if ( #ARGV != 1 ) {
print "Usage: GetTable <sql query file>\n";
exit 1;
}
open QFILE, $ARGV[0] or die "File $ARGV[0]: $! \n";
my $flag = 0;
my $query = "";
my $conds = "select|insert|update|delete";
while ( <QFILE> ) {
next if ( /^$/ );
if ( $flag == 1 ) {
$query .= $_;
if ( /;\s*$/ ) {
$flag = 0;
&process( $query );
}
}
elsif ( /^\s*($conds).*;\s*/i ) {
&process( $_ );
}
elsif ( /^\s*($conds)/i ) {
$flag = 1;
$query = $_;
}
}
close QFILE;
Two important skills to learn as a programmer are a) accuracy in following instructions and b) reading the error message carefully.
You started by running GetTable.pl. But that program requires a parameter (the name of an SQL file to analyse) and the error message tried to tell you that.
I don't know why, but instead of doing what the error message told you to do (which would have been to run perl GetTable.pl test.sql) you decided to ask Perl to run your SQL file.
The second error message you got was the Perl compiler trying to make sense of the SQL that you asked it to run. But the Perl compiler doesn't understand SQL, it understands Perl. So it's no surprise that it got confused.
To fix it, do what your first error message suggested—run the command
$ perl GetTable.pl test.sql
My shell script is written in cygwin for windows:
// main.sh
#!/bin/bash
[ "$#" -lt 1 ] && echo "Usage: thisscript.sh <filename.txt>" && exit 0
filename=`basename -s .txt $1`
i=0
while [ $i == 0 ]
do
phantomjs --web-security=no myXHR.js $filename.txt
logLastLine=`tail -n 1 $filename.log`
if [[ "$logLastLine" =~ "Error" ]]; then
echo "Error occurs, now keep looping it..."
elseif [[ "$logLastLine" =~ "503" ]]; then
echo "Error occurs, now keep looping it..."
elseif [[ "$logLastLine" =~ "500" ]]; then
echo "Error occurs, now keep looping it..."
else
echo "Complete! Exiting the execution..."
i=1
fi
done
And here are the codes contained in the myXHR.js
// myXHR.js
phantom.onError = function(msg, trace) {
console.log("PhantomJS Error");
phantom.exit();
};
var fs = require('fs'), system = require('system');
if (system.args.length < 2) {
console.log("Usage: myXHR.js <FILE>");
}
var content = '',
f = null,
lines = null,
eol = "\n";
try {
f = fs.open(system.args[1], "r");
filename=system.args[1].replace(/\.txt/,"");
content = f.read();
} catch (e) {
console.log(e);
}
if (f) {
f.close();
}
var request = new XMLHttpRequest();
if (content) {
lines = content.split(eol);
for (i=0; i<(lines.length-1);i++) {
request.open('GET', "http://stackoverflow.com/", false);
request.send();
if (request.status === 200) {
try {
fs.write($filename.log, line[i] + "Succeed!", 'a');
} catch(e) {
console.log(e);
}
} else {
try {
fs.write($filename.log, line[i] + "Error!", 'a');
} catch(e) {
console.log(e);
}
}
}
phantom.exit();
To illustrate, the javascript, executed by PhantomJS, are reading 1st argument(a filename.txt file), passed into the shell script, line by line. For each line it sends a XMLHttpRequest to check the request status and writes it into filename.log file.
Error status number includes 503 and 500. Luckily these statuses are less likely to occur again if I resend the same XMLHttpRequest. So what I need to do is to set up a error handler which is for resend the same XMLHttpRequest when errors occur.
In this error handler, I use X=${tail -n 1 log} to see if there is a error status number(containing "503" or "500" string). For instance, if [[ "$X" =~ "503" ]]; then restart the execution of the javascript, by not giving i=1 and while loop never exits. Until it has finished reading the last line of the imported file without any error status numbers.
(I know it is awkward to handle error like this, but it was a quick solution that came to my mind.)
But this is theoretical. In practice, this script ended with an error "Memory exhausted". I reckon this error is triggered by the large amount of lines(>100k) in the $1 file, and it occurs in the JavaScript execution part. I used free -m command to get memory usage information, and I noticed that when Javascript is running, the used swap is increasing!
Could anybody teach me how to release the memory when the scripts is being executed.
So I have this small script which checks two log files for a specific line and compares the lines.
The script is used on several different Windows Bamboo Agents. But on one it just hangs and doesn't exit. Since the script is used in bamboo the whole job hangs, when this script doesn't exit.
When I check the computer via remote access and kill the script the job continues until it reaches the script again.
This is the script, which is started by another script.
#! /usr/bin/perl
my $naluresult = 2;
my $hevcresult = 2;
my $hevcfailed = 0;
use strict;
use warnings;
#---------------------------------------------
#check for $ARGV[0] and $ARGV[1]
open( my $nalulog, "<", $ARGV[1] )
or die "cannot open File:$!\n\n";
while (<$nalulog>) {
chomp;
$_ =~ s/\s+//g;
if ( $_ =~ m/MD5:OK/ ) {
$naluresult = 1;
} else {
if ( $_ =~ m/MD5:MISSING/ ) {
$naluresult = 0;
}
}
}
close $nalulog;
#---------------------------------------------
open( my $hevclog, "<", $ARGV[0] )
or die "cannot open File:$!\n\n";
while (<$hevclog>) {
chomp;
$_ =~ s/\s+//g;
if ( $_ =~ m/MD5check:OK/ ) {
$hevcresult = 1;
last;
} else {
if ( $_ =~ m/MD5check:FAILED/ ) { $hevcfailed = 1; }
}
if ( $hevcfailed == 1 ) {
#do stuff
}
}
close $hevclog;
#---------------------------------------------
if ( $hevcresult == 2 ) {
print("Missing MD5 status in HEVC Output");
exit(-1);
} elsif ( $naluresult == 2 ) {
print("Missing MD5 status in NALU Output");
exit(-2);
} else {
if ( $naluresult == $hevcresult ) { exit(0); }
else {
#different if-statements to print() to log
exit(1);
}
}
#---------------------EOF---------------------
If your files are just normal disk files that aren't being simultaneously written to by other processes, or locked, or anything like that, then there is nothing in the code you have here that should hang. If the files are both reasonable sizes, the code you have here should read through the files and finish.
However, if one of the files is locked, or is immensely large, or if you have other code that can get stuck in an infinite loop, that would explain why your program is hanging.