Create new system-call in xv6 that returns data about an open files for all running processes - system-calls

Im started to learn about xv6.
And I'm trying to add a new system call that will print the list of open files for all running processes.
It has to print pid of each process, its file descriptor number (0,1,2- for each pid), if the file is regular or piped and if the file is readable of writable.
So I know is how to get the pid. Here is an example of a code:
struct proc *p;
sti();
acquire(&ptable.lock);
cprintf("name \t pid \t type \t \n");
for (p=ptable.proc; p<&ptable.proc[NPROC]; p++){
cprintf("%s \t %d \n", p->name, p->pid);
}
}
release (&ptable.lock);
What I don't know and couldn't find on the internet is how to check if file named by file descriptor is writable\riadable\both
And I don't know how to check if the type of the file named by file descriptor is pipe\regular.
I looked at file.h and there are fields like type(FD_NONE, FD_PIPE, FD_INODE), char readable,char writable.
But I dont understand how to get them...
If you have any resources with subtitle info to share with me or if you can help, I would be happy to hear.
Thanks a lot!

Check out
struct proc in proc.h
functions in file.c
You should be able to get a pointer to the beginning of the open files array like this:
struct file* fp = (struct file*) &p->ofile;
From there, you can copy the same syntax from the ptable loop to loop through the files. And to check if a file is readable, functions in file.c just check the readable flag:
if(fp->readable && fp->type == FD_PIPE)
// do some logic

Related

Input argument is a file or an either content to Perl

I wrote a Perl script to convert from TEX format to JSON format.
Calling in the batch file:
perl -w C:\test\support.pl TestingSample.tex
This is working fine now.
Perl script having two types of input from another program (might be any platform/technology) one is file (*TEX) or else content (*TEX file) either this or that option.
How can I receive the full content as the input to the Perl script?
Now my Perl script is:
my $texfile = $ARGV[0]; my $texcnt = "";
readFileinString($texfile, \$texcnt);
I am trying to update:
perl -w C:/test/support.pl --input $texcnt" #Content is Input
I am receiving error message:
The command line is too long.
Could someone please advice?
First of all regarding the error you're getting:
Perl (or your shell) is complaining that your input argument is too long.
Parsing entire files as arguments to scripts is generally a bad idea anyway, for example quotation mark escaping etc. might not be handled and thus leave a wide open vulnarbility to your entire system!
So the solution to this is to modify your script so that it can take the file as an argument (if that isn't already the case) and if you really need to have an entire file's content parsed as an argument I'd really advise you to create a temporary file in /tmp/ (if on Linux) or in your %TEMP% directory on Windows and parse the file the content into the file and after that give your support.pl script the new temp file as an argument.

Perl Copy to more than one Location

Hello I'm attempting to copy a file to more then one location. I have written a script that will copy files using File::Find and File::Copy together to one location but I can not get the script to copy to a second or third location. I've tried to add a second variable target2 to the script so I can also copy the JPG files to this second target location. When I try to do this I get an error message. I want the copy to run on a loop that will copy the files X amount of seconds so I added the sleep function in as well. Can anyone explain to me why I can't copy to more than one location or help me find a way to do this? Thank you.
while (1)
{ sleep (10);
find(
sub {
if (-f &&/\.jpg$/i) {
print "$File::Find::name -> $target, $target2";
copy($File::Find::name, $target ,$target2)
or die(q{copy failed:} . $!);
}
},
#source
);
}
Error message: Bad Buffer size for copy: 0
copy function can't copy to 2 destinations. Call it twice:
copy($File::Find::name, $target);
copy($File::Find::name, $target2);
Look here to see the parameters explanation: http://perldoc.perl.org/File/Copy.html#SYNOPSIS
As the docs say:
An optional third parameter can be used to specify the buffer size
used for copying. This is the number of bytes from the first file,
that will be held in memory at any given time, before being written to
the second file.
So, when you specified the third parameter, Perl understood, that you want to set the buffer size manually. But you gave a string instead of a number, so it converted the string to a number: 0, and gave you an error:
Bad Buffer size for copy: 0

opening a batch file that opens a text file in python

I am writing a script that can execute a batch file, which needs to open a file in the same folder first. My current code is:
from subprocess import Popen
p = Popen("Mad8dl.bat <RUNTHISTO.txt>", cwd=r"C:\...\test")
stdout, stderr = p.communicate()
where the ... is just the path to the folder. However, everytime I run it I get the syntax error:
The syntax of the command is incorrect
Any help regarding the syntax would be greatly appreciated.
First, you should probably remove the < and > angle brackets from your code; just pass the filename, without any brackets, to your batch file. (Unless your filename really does contain < and > characters, in which case I really want to know how you managed it since those characters are forbidden in filenames in Windows).
Second, your code should look like:
from subprocess import Popen, PIPE
p = Popen(["Mad8dl.bat", "RUNTHISTOO.txt"], cwd=r"C:\...\test", stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate()
Note the list containing the components of the call, rather than a single string. Also note that you need to specify stdout=PIPE and stderr=PIPE in your Popen() call if you want to use communicate() later on.

Using a .fasta file to compute relative content of sequences

So me being the 'noob' that I am, being introduced to programming via Perl just recently, I'm still getting used to all of this. I have a .fasta file which I have to use, although I'm unsure if I'm able to open it, or if I have to work with it 'blindly', so to speak.
Anyway, the file that I have contains DNA sequences for three genes, written in this .fasta format.
Apparently it's something like this:
>label
sequence
>label
sequence
>label
sequence
My goal is to write a script to open and read the file, which I have gotten the hang of now, but I have to read each sequence, compute relative amounts of 'G' and 'C' within each sequence, and then I'm to write it to a TAB-delimited file the names of the genes, and their respective 'G' and 'C' content.
Would anyone be able to provide some guidance? I'm unsure what a TAB-delimited file is, and I'm still trying to figure out how to open a .fasta file to actually see the content. So far I've worked with .txt files which I can easily open, but not .fasta.
I apologise for sounding completely bewildered. I'd appreciate your patience. I'm not like you pros out there!!
I get that it's confusing, but you really should try to limit your question to one concrete problem, see https://stackoverflow.com/faq#questions
I have no idea what a ".fasta" file or 'G' and 'C' is.. but it probably doesn't matter.
Generally:
Open input file
Read and parse data. If it's in some strange format that you can't parse, go hunting on http://metacpan.org for a module to read it. If you're lucky someone has already done the hard part for you.
Compute whatever you're trying to compute
Print to screen (standard out) or another file.
A "TAB-delimite" file is a file with columns (think Excel) where each column is separated by the tab ("\t") character. As quick google or stackoverflow search would tell you..
Here is an approach using 'awk' utility which can be used from the command line. The following program is executed by specifying its path and using awk -f <path> <sequence file>
#NR>1 means only look at lines above 1 because you said the sequence starts on line 2
NR>1{
#this for-loop goes through all bases in the line and then performs operations below:
for (i=1;i<=length;i++)
#for each position encountered, the variable "total" is increased by 1 for total bases
total++
}
{
for (i=1;i<=length;i++)
#if the "substring" i.e. position in a line == c or g upper or lower (some bases are
#lowercase in some fasta files), it will carry out the following instructions:
if(substr($0,i,1)=="c" || substr($0,i,1)=="C")
#this increments the c count by one for every c or C encountered, the next if statement does
#the same thing for g and G:
c++; else
if(substr($0,i,1)=="g" || substr($0,i,1)=="G")
g++
}
END{
#this "END-block" prints the gene name and C, G content in percentage, separated by tabs
print "Gene name\tG content:\t"(100*g/total)"%\tC content:\t"(100*c/total)"%"
}

Casting Command Line Arguments?

i have a command line executable program that accepts a configuration file as it's one argument for launch. the configuration file contains only 2 lines of code:
#ConfigFile.cfg
name=geoffrey
city=montreal
currently, the wrapper program that i'm building for this command line executable program writes the configuration file to disk and than sends that written file as the argument to launch the program on the command line.
> myProgram.exe configFile.cfg
is it possible to cast these configuration file entries as the configuration file, allowing me to bypass having to write the configuration file to disk but still allow the program to run as if it's reading from a configuration file?
perhaps something like the following:
> myProgram.exe configFile.cfg(name=geoffrey) configFile.cfg(city=montreal)
If you don't control the source for the program you're wrapping, and it doesn't already provide a facility to receive input in another way, you're going to find it difficult at best.
One possibility would be to intercept the file open and access calls used by the program though this is a horrible way to do it.
It would probably involve injecting your own runtime libraries containing (for C) fopen, fclose, fread and so on, between the program and the real libraries (such as using LD_LIBRARY_PATH or something similar), and that's assuming it's not statically linked. Not something for the faint of heart.
If you're worried about people being able to see your file, there's plenty of ways to avoid that, such as by creating it with rwx------ permissions in a similarly protected directory (assuming UNIX-like OS). That's probably safer than using command line arguments which any joker logged in could find out with a ps command.
If you just don't want the hassle of creating a file, I think you'll find the hassle of avoiding it is going to be so much more.
Depending on what you're really after, it wouldn't take much to put together a program that accepted arguments, wrote them to a temporary file, called the real program with that temporary file name, then deleted the file.
It would still be being written to disk, but that would no longer be the responsibility of your wrapper program. Something along the lines of (a bit rough, but you should get the idea):
#include <stdio.h>
#define PROG "myProgram"
int main (int argCount, char *argVal[]) {
char *tmpFSpec;
FILE *fHndl;
int i;
char *cmdBuff;
tmpFSpec = getTempFSpec(); // need to provide this.
cmdBuff = malloc (sizeof(PROG) + 1 + strlen (tmpFSpec) + 1);
if (cmdBuff == NULL) {
// handle error.
return 1;
}
fHndl = fopen (tmpFSpec, "w");
if (fHndl == NULL) {
// handle error.
free (cmdBuff);
return 1;
}
for (i = 1; i < argCount; i++)
fprintf (fHndl, "%s\n", argVal[i]);
sprintf (cmdBuff, "%s %s", PROG, tmpFSpec);
system (cmdBuff);
return 0;
}