I'm developing my own version of getopt() in assembly and trying to get my head wrapped around this snippet, specifically line 476
if (argc < 1)
return -1;
As the normal calling convention would be something like this;
int c = getopt( argc, argv, "vm:drx:");
and assuming the programmer hasn't done anything with argc before hand, the only reason I can think it would be there is that some flavor of Linux, possibly non POSIX compliant would'nt pass argv[0] application path & name. Therefore, argc could be zero. Is there any credence to this conjecture?
Of the 12 times this variable is used in this procedure, it's only ever asserted or copied, never modified and not referenced at all in the two levels of procedure before this.
Consider this:
#include <stdio.h>
#include <unistd.h>
int main(int argc, char* argv[])
{
execve("./testargc", NULL, NULL);
}
And this program:
#include <stdio.h>
int main (int argc, char* argv[])
{
printf("%d\n", argc);
}
The first one execs the 2nd one with no arguments. The pathname is not passed in and as a result argc is 0.
Related
According to strace, lseek(fd, 0, SEEK_END) = 9223372036854775807 when fd refers to a directory. Why is this syscall succeeding at all? What does lseek() mean for a dir fd?
On my test system, if you use opendir(), and readdir() through all the entries in the directory, telldir() then returns the same value:
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include <dirent.h>
int main(int argc, char *argv[]) {
int fd = open(".", O_RDONLY);
if (fd < 0) {
perror("open");
return 1;
}
off_t o = lseek(fd, 0, SEEK_END);
if (o == (off_t)-1) {
perror("lseek");
return 1;
}
printf("Via lseek: %ld\n", (long)o);
close(fd);
DIR *d = opendir(".");
if (!d) {
perror("opendir");
return 1;
}
while (readdir(d)) {
}
printf("via telldir: %ld\n", telldir(d));
closedir(d);
return 0;
}
outputs
Via lseek: 9223372036854775807
via telldir: 9223372036854775807
Quoting from the telldir(3) man page:
In early filesystems, the value returned by telldir() was a simple file offset within a directory. Modern filesystems use tree or hash structures, rather than flat tables, to represent directories. On such filesystems, the value returned by telldir() (and used internally by readdir(3)) is a "cookie" that is used by the implementation to derive a position within a directory. Application programs should treat this strictly as an opaque value, making no assumptions about its contents.
It's a magic number that indicates that the index into the directory's contents is at the end. Don't count on the number always being the same, or being portable. It's a black box. And stick with the dirent API for traversing directory contents unless you really know exactly what you're doing (Under the hood on Linux + glibc, opendir(3) calls openat(2) on the directory, readdir(3) fetches information about its contents with getdents(2), and seekdir(3) calls lseek(2), but that's just implementation details)
I'm currently doing the CS50 Harvard Course and I'm stuck in problem set 2.
I made this program that takes a name and prints the initials, it takes the name in the command line. How can I use get_string() instead of argv, and argc wich is very unorthodox and sloppy, so I can prompt the user to give me her/his name. Thank you.
#include <cs50.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
int main(int argc, string argv[])
{
//How do I use Get_string() so I don't have to use argv and argc??
//iterate over strings on the vector (words)
for (int i = 0; i < argc; i++)
{
//prints the 0 character of each string, use "toupper" to convert into capital letters
printf("%c", toupper(argv[i][0]));
}
printf("\n");
}
use Array,
let's say for 10 names
string name[10];
for (int i = 0; i < 10; i++)
{
name[i] = get_string("Enter your name: /n");
}
So I've been trying to access command line arguments with indices larger than argc in C++ (because why not) and discovered that there are actually some parameters passed on to the program. The following code produces the following result in my Ubuntu 14.04:
#include <cstdio>
int main (int argc, char** argv) {
for (int i=argc+1; argv[i]!=0; i++)
printf("%3d %s\n", i, argv[i]);
}
This is the output:
2 XDG_VTNR=7
3 LC_PAPER=tr_TR.UTF-8
4 LC_ADDRESS=tr_TR.UTF-8
5 XDG_SESSION_ID=c2
6 XDG_GREETER_DATA_DIR=/var/lib/lightdm-data/kubuzetto
7 SELINUX_INIT=YES
8 LC_MONETARY=tr_TR.UTF-8
9 CLUTTER_IM_MODULE=xim
(and so on)
What is this and is it distro-dependent?
Don't run past argc, it's not defined.
In this case, we know what happened. You see, main() is declared and called as
extern int main(int argc, char **argv, char **envp);
and it just so happens that the the way argv and envp are built leaves envp right after argv, so running off the end encounters envp.
It might change someday, so don't depend on this working. If you wanna depend on the kernel's passing method, provide the kernel's entry point yourself (which must be done in asm [or possibly a naked function] as it doesn't look like a function call).
This came up in a class recently. The problem is the first occurrence of "ptr" in the if. The error is "expression must be a modifiable value".
#include "stdafx.h"
#include <iostream>
using namespace std;
int _tmain(int argc, _TCHAR* argv[])
{
int * ptr = nullptr;
int i = 7;
if (ptr == nullptr && ptr = &i)
cout << *ptr;
return 0;
}
Parentheses are your friend. The C/C++ operator precedence table is deep and some aspects are not intuitive.
In this case, logical AND (&&) binds tighter than assignment (=). ("Binds tighter" == "is of higher precedence".)
When in doubt, I always use a quick google search for "c operator precedence table" to get a bunch of result pages all of which provide a helpful table in order of precedence. (Actually, when in doubt in my own code I always just add the parentheses in the first place.)
I am trying to write a program that will constantly keep track of the changes in a file and do several actions accordingly. I am using inotify and select within a loop to track file modifications in a non-blocking manner. The basic structure of the file tracking portion of my program is as follows.
#include <cstdio>
#include <signal.h>
#include <limits.h>
#include <sys/inotify.h>
#include <fcntl.h>
#include <iostream>
#include <fstream>
#include <string>
int main( int argc, char **argv )
{
const char *filename = "input.txt";
int inotfd = inotify_init();
char buffer[1];
int watch_desc = inotify_add_watch(inotfd, filename, IN_MODIFY);
size_t bufsiz = sizeof(struct inotify_event) + 1;
struct inotify_event* event = ( struct inotify_event * ) &buffer[0];
fd_set rfds;
FD_ZERO (&rfds);
struct timeval timeout;
while(1)
{
/*select() intitialisation.*/
FD_SET(inotfd,&rfds); //keyboard to be listened
timeout.tv_sec = 10;
timeout.tv_usec = 0;
int res=select(FD_SETSIZE,&rfds,NULL,NULL,&timeout);
FD_ZERO(&rfds);
printf("File Changed\n");
}
}
I checked the select manual page and reset the fd_set descriptor each time select() returns. However, whenever I modify the file (input.txt), this code just loops infinitely. I not very experienced using inotify and select, so, I am sure if the problem is with the way I use inotify or select. I would appreciate any hints and recommentations.
you have to read the contents of the buffer after the select returns. if the select() finds data in the buffer, it returns. so, perform read() on that file descriptor (inotfd). read call reads the data and returns amount of bytes it read. now, the buffer is empty and in the next iteration, the select() call waits until any data is available in the buffer.
while(1)
{
// ...
char pBuf[1024];
res=select(FD_SETSIZE,&rfds,NULL,NULL,&timeout);
read(inotfd,&pBuf, BUF_SIZE);
// ...
}