qbasic what is the difference between open "file.dat" for input as #1 or input as #2 - qbasic

Now i am on grade 10 and i am learning about open"file.dat" for input/output as #n
once have a look at my program
cls
open "samrat.dat" for output as #1
input "enter your name";n$
write #1,n$
close #1
end
so with this program i save my name to the file
now i use output as #n to print this number. have a look at my next program
cls
open "samrat.dat" for input as #1
input #1,n$
print n$
close #1
end
so this program will print my or user name. but one thing is confusing me. if i will use open "samrat.dat" for input as #5 and change the #1 into #5 in all the places the output is same. I dont quite understand how it works. if #1 is same as #1000 what is the need of other number.
please tell me

You're right, your program will work as long as you use the same filenumber on all the places. The filenumber is just a token to tell the different files appart in your program.
It is possible for a program to access more than one file at the same time.
For example you could read from one file, process the input, and then write it to another file.
OPEN infile$ FOR INPUT AS #1
OPEN outfile$ FOR OUTPUT AS #2
INPUT #1, A$
A$ = UCASE$(A$)
PRINT #2, A$
'etc.

Related

perl print to a file and STDOUT which is the file

My program is trying to print to a file which for it is the STDOUT.
To say, print "text here"; prints to a file x.log , while I am also trying to print to the file x.log using file-handler method as in print FH1 "text here"; . I notice that when the file-handler method statement is provided first and then followed by the STDOUT procedure. My second print can override the first.I would like to know more on why this occurs.
This makes me think of a race condition or that the file-handler is relatively slow (if it goes through buffer?) than the STDOUT print statements. This I am not sure on how if that is the way Perl works. Perl version - 5.22.0
As far as I understand your program basically looks like this:
open(my $fh,'>','foobar.txt');
print $fh "foo\n";
print "bar\n"; # prints to STDOUT
And then you use it in a way that STDOUT is redirected in the shell to the same file which is already opened in your program:
$ perl test.pl > foobar.txt
This will open two independent file handles to the same file: one within your program and the other within the shell where you start the program. Both file handles manage their own file position for writing, start at position 0 and advance the position after each write.
Since these file handles are independent from each other they will not care if there are other file handles dealing currently with this file, no matter if these other file handles are inside or outside the program. This means that these writes will overwrite each other.
In addition to this there is also internal buffering done, i.e. each print will first result into a write into some internal buffer and might result immediately into a write to the file handle. When data are written to the file handle depends on the mode of the file handle, i.e. unbuffered, line-buffered or a buffer of a specific size. This makes the result kind of unpredictable.
If you don't want this behavior but still want to write to the same file using multiple file handle you better use the append-mode, i.e. open with >> instead of > in both Perl code and shell. This will make sure that all data will be appended to the end of the file instead of written to the file position maintained by the file handle. This way data will not get overwritten. Additionally you might want to make the file handles unbuffered so that data in the file end up in the same order as the print statements where done:
open(my $fh,'>>','foobar.txt');
$fh->autoflush(1); # make $fh unbuffered
$|=1; # make STDOUT unbuffered
print $fh "foo\n";
print "bar\n"; # prints to STDOUT
$ perl test.pl >> foobar.txt

Discarding extra newlines on STDIN in Perl without Term::ReadKey

I've been digging through search engine results and Stack Overflow trying to solve this problem, and I've tried a dozen different "solutions" to no avail. I cannot use Term::ReadKey, as most solutions suggest, due to limitations of my environment.
The existing Perl script does:
my $mode1=<STDIN>;
chomp($mode1);
but many of the prompts don't evaluate the input - for example the user could enter an arbitrary string - but the script only chomps the input and then ignores the contents. Several prompts ask for input but pressing [ENTER] without entering input applies default values.
If the user gets impatient while the script is in a blocking function or checks to see if the terminal is responding by pressing [ENTER], those newline characters advance the script inappropriately when the blocking function ends. I don't want to rely on user training instead of automation, and it seems like there must be an easy obvious solution but I can't seem to dig one up.
It isn't originally my script, and its author admits it was quick-and-dirty to begin with.
The 4-argument select function is a little cryptic to use, but it can tell you, in many cases, whether there is any unread input waiting on an input filehandle. When it is time for your program to prompt the user for input, you can use select to see if there is any extra input on STDIN, and clear it before you prompt the user again and ask for additional input.
print "Prompt #48: are you tired of answering questions yet? [y/N]";
clearSTDIN();
$ans48 = <STDIN>;
...
sub clearSTDIN {
my $rin = "";
vec($rin, fileno(STDIN), 1) = 1;
my ($found,$left) = select $rin,undef,undef,0;
while ($found) {
# $found is non-zero if there is any input waiting on STDIN
my $waste = <STDIN>; # consume a line of STDIN
($found,$left) = select $rin,undef,undef,0;
}
seek STDIN,0,1; # clears eof flag on STDIN handle
}
Is the easy solution to close STDIN?
print "Are you sick of answering questions yet? [y/N] ";
$ans = <STDIN>;
if ($ans =~ /^y/i) {
close STDIN;
# from now on, further calls to <STDIN> will immediately
# return undef and will assign default values
}
...

Output stdin, stdout to file and console using Perl

I am trying a simple questionnaire using perl. I want to record the responses in a log file as and when a user inputs it. I'm having problem in redirecting the stdin to file.
Below is the code I implemented. Refer this.
open my $tee, "|-", "tee some_file.out";
print $tee "DO you want to continue?(y/n)\n";
$var=<STDIN>;
$var =~ s/[\n\r\f\t]//g;
if($var eq "y"){
print $tee "Enter\n";
}
close $tee;
The output I'm getting now is, only after user input is provided the question is printed.
#in console
y
DO you want to continue?(y/n)
Enter
#some_file.out
DO you want to continue?(y/n)
Enter
Below is the expected output:
#in console
DO you want to continue?(y/n)
y
Enter
#some_file.out
DO you want to continue?(y/n)
y
Enter
I also found Duplicate stdin to stdout but really couldn't achieve what I want to.
Am I missing something?!
Is there any cleaner solution available?
First of all, never use the phrase "redirecting the stdin to..." because stdin is input. It doesn't go to anything. It comes from somewhere.
It seems that what you expected is to have a copy of $var appear in your log file. Since you never printed $var to $tee there's no way that could happen.
So why did you think $var would appear in the log file? From the way you have shown us a copy of the log file next to a copy of what you see on the terminal, I guess that your reasoning went something like this:
The tee put all of the output into the log file
The tee also put all of the output on the terminal
My program didn't output anything else besides what went into the tee
The screen contents should match the log file
But there's a hidden assumption that's required to reach the conclusion:
3a. Nothing else was written to the terminal besides my program's output
And that's the part which is incorrect. When you type y into the terminal while your program is running, the terminal itself echoes what you type. It prints a copy in the terminal window, and also sends the character to your program's stdin. The y that you see on screen is not part of your program's output at all.
Since the echoing is done by the terminal and not by your program, you can't instruct it to also send a copy to your log file. You need to explicitly print it there if you want it to be logged.
You can ask the terminal to stop echoing, and then you take responsibility for printing the characters as they are typed so the user can see what they're typing. If you want to try that, see the Term::ReadKey module.
Or if what you really want is a complete record of everything that appeared on the terminal during the run of your program, maybe you should run it in the standard unix tool script, which is made for exactly that purpose.
(Side note: Did you know about the IO::Tee module? you can have teed output without an external process)

How to run a local program with user input in Perl

I'm trying to get user input from a web page written in Perl and send it to a local program (blastp), then display the results.
This is what I have right now:
(input code)
print $q->p, "Your database: $bd",
$q->p, "Your protein is: $prot",
$q->p, "Executing...";
print $q->p, system("blastp","-db $bd","-query $prot","-out results.out");
Now, I've done a little research, but I can't quite grasp how you're supposed to do things like this in Perl. I've tried opening a file, writing to it, and sending it over to blastp as an input, but I was unsuccessful.
For reference, this line produces a successful output file:
kold#sazabi ~/BLAST/pataa $ blastp -db pataa -query ../teste.fs -out results.out
I may need to force the bd to load from an absolute path, but that shouldn't be difficult.
edit: Yeah, the DBs have an environmental variable, that's fixed. Ok, all I need is to get the input into a file, pass it to the command, and then print the output file to the CGI page.
edit2: for clarification:
I am receiving user input in $prot, I want to pass it over to blastp in -query, have the program blastp execute, and then print out to the user the results.out file (or just have a link to it, since blastp can output in HTML)
EDIT:
All right, fixed everything I needed to fix. The big problem was me not seeing what was going wrong: I had to install Tiny:Capture and print out stderr, which was when I realized the environmental variable wasn't getting set correctly, so BLAST wasn't finding my databases. Thanks for all the help!
Write $prot to the file. Assuming you need to do it as-is without processing the text to split it or something:
For a fixed file name (may be problematic):
use File::Slurp;
write_file("../teste.fs", $prot, "\n") or print_error_to_web();
# Implement the latter to print error in nice HTML format
For a temp file (better):
my ($fh, $filename) = tempfile( $template, DIR => "..", CLEANUP => 1);
# You can also create temp directory which is even better, via tempdir()
print $fh "$prot\n";
close $fh;
Step 2: Run your command as you indicated:
my $rc = system("$BLASTP_PATH/blastp", "-db", "pataa"
,"-query", "../teste.fs", "-out", "results.out");
# Process $rc for errors
# Use qx[] instead of system() if you want to capture
# standard output of the command
Step 3: Read the output file in:
use File::Slurp;
my $out_file_text = read_file("results.out");
Send back to web server
print $q->p, $out_file_text;
The above code has multiple issues (e.g. you need better file/directory paths, more error handling etc...) but should start you on the right track.

Perl security, the print statement?

I don't know perl at all, but I need to change an exitsting program to give a clearer debug output.
This is the statement:
print $lfh "$ts\t$tid\t$msg\n";
where $msg will be created by joining the arguments of the function like this:
my $msg = join( "\t", #_ );
Somewhere in $msg I would like to add one of the command line arguments the user has supplied when calling the program. Is that risk for an exploit if printed to stdout?
Note also that $lfh will be taken from an environment variable (set by the script itself earlier on) if it is to write to a file, like this:
open my $lfh, ">>", $ENV{GL_LOGFILE}
The info I could find on perl security says nothing about the print statement, so maybe I'm just completely paranoid, but better safe than sorry...
You can pass arbitrary data to print, and it won't break. However:
printing to a file handle may go through various IO layers like encodings. Not all data may be valid for these layers. E.g. encoding layers will either use a substitution character or terminate the script when handed invalid data.
Perl's print doesn't care about control characters like NULs, backspaces, or carriage returns and just passes them through. Depending on how the output is viewed, it might look jumbled or could break the viewing application. Example: User input is equal to the string "\rHAHA". When you print "something$userinput", you might see HAHAthing when displayed on the console, because the carriage returns places the cursor in the 1st column. If the user input contains newlines, your output records could be broken up, e.g. "foo${userinput}bar" might become the two lines foo and bar.
If the input is condidential information, the output will be confidential as well, so you should make sure that the output can't be viewed by anyone. E.g. displaying the output including debug information on a web page could allow attackers to obtain more information about your system.