how to write one entry in /var/run/utmp? - linux

Based on this bug i'm trying to write an entry in /var/run/utmp to simulate the problem http://bugs.debian.org/cgi-bin/bugreport.cgi?bug=528060 , i tryed with this code taken from manpages, but didn't work
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <utmp.h>
int
main(int argc, char *argv[])
{
struct utmp entry;
system("echo before adding entry:;who");
entry.ut_type = USER_PROCESS;
entry.ut_pid = getpid();
strcpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"));
/* only correct for ptys named /dev/tty[pqr][0-9a-z] */
strcpy(entry.ut_id, ttyname(STDIN_FILENO) + strlen("/dev/tty"));
time(&entry.ut_time);
strcpy(entry.ut_user, getpwuid(getuid())->pw_name);
memset(entry.ut_host, 0, UT_HOSTSIZE);
entry.ut_addr = 0;
setutent();
pututline(&entry);
system("echo after adding entry:;who");
exit(EXIT_SUCCESS);
}

I solved my problem with this code
#include <string.h>
#include <stdlib.h>
#include <pwd.h>
#include <unistd.h>
#include <utmp.h>
int
main(int argc, char *argv[])
{
struct utmp entry;
system("echo before adding entry:;who");
entry.ut_type = USER_PROCESS;
entry.ut_pid = getpid();
strcpy(entry.ut_line, ttyname(STDIN_FILENO) + strlen("/dev/"));
/* only correct for ptys named /dev/tty[pqr][0-9a-z] */
strcpy(entry.ut_id, ttyname(STDIN_FILENO) + strlen("/dev/tty"));
time(&entry.ut_time);
//strcpy(entry.ut_user, getpwuid(getuid())->pw_name);
strcpy(entry.ut_user, "pippo");
memset(entry.ut_host, 0, UT_HOSTSIZE);
entry.ut_addr = 0;
setutent();
pututline(&entry);
system("echo after adding entry:;who");
exit(EXIT_SUCCESS);
}

Related

Inter process communication using FIFO

Client server must pass to the Server process a filename and the Server process must return the number of lines in the file. My problem is that the received variable only contains 6 characters of the filename and it ends up by throwing segmentation fault dump core error. Do you know why this happens? This is my code:
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
int main(){
int fd1,fd2;
const char *fifo1="./fifo1Channel";
const char *fifo2="./fifo2Channel";
mkfifo(fifo1,0666);
mkfifo(fifo2,0666);
char filename[30];
printf("Give me a filename:\n");
fgets(filename,30,stdin);
strtok(filename,"\n");
int pid=fork();
if(pid>0){
char received[30], ch;
FILE *fp;
fd1=open(fifo1, O_RDONLY);
read(fd1,received,strlen(received));
close(fd1);
printf("From server process:%s\n",received);
fp=fopen(received,"r");
int nrOfLines=0;
for(ch=getc(fp);ch!=EOF;ch=getc(fp))
if(ch=='\n')
nrOfLines++;
fd2=open(fifo2, O_WRONLY);
write(fd2,&nrOfLines,sizeof(nrOfLines));
close(fd2);
return 0;
}
if(pid==0){
int receivedNumber;
fd1=open(fifo1,O_WRONLY);
write(fd1,filename,strlen(filename));
close(fd1);
fd2=open(fifo2,O_RDONLY);
read(fd2,&receivedNumber,sizeof(receivedNumber));
close(fd2);
printf("From client process: %d\n",receivedNumber);
return 0;
}
return 0;
}
I think the problem was in server process. I replaced strlen(received) with 30, the maximum number of characters of filename, in function read and it works now!

where fcntl saves locking information

I wonder to understand where fcntl c++ function saves information about locked files. I know that it saves some information on /proc/locks , but fcntl identify lock even if it locked by another host
In my first host I locked some file By F_WRLCK.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_WRLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDWR ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
When I am traying to lock the same file on my second host by F_RDONLY it doesn't work.
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include<iostream>
main() {
int fd;
struct flock lock;
lock.l_type=F_RDLCK;
lock.l_start=0;
lock.l_whence= SEEK_SET;
lock.l_len=0;
printf("open %d\n",fd=open("/u/embedit/places/scratch/gtevos/ts16nxq42p11assrl16kaa03/ts16nxq42p11assrl16kaa.cpj", O_RDONLY ));
int rc = fcntl(fd, F_SETLK, &lock);
std::cout<<rc<<std::endl;
std::cin>>fd;
}
I just want to understand which mechanism is used that provide ability to right identify locks.

setsockopt IPT_SO_SET_REPLACE flag return error (linux)

I try to use setsockopt with the flag IPT_SO_SET_REPLACE but i keep getting the wired error from errno Protocol not available this is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sched.h>
#include <linux/sched.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <linux/netlink.h>
#include <unistd.h>
#include <sys/ptrace.h>
#include <netinet/in.h>
#include <net/if.h>
#include <linux/netfilter_ipv4/ip_tables.h>
#include <fcntl.h>
int main(void) {
int sock;
int ret;
void *data;
size_t size;
struct ipt_replace *repl;
sock = socket(PF_INET, SOCK_RAW, IPPROTO_RAW);
if (sock == -1) {
perror("socket");
return -1;
}
size = sizeof(struct ipt_replace);
data = malloc(size); Protocol not available
if (data == NULL) {
perror("malloc");
return -1;
}
memset(data, 0, size);
repl = (struct ipt_replace *) data;
repl->num_counters = 0x1;
repl->size = 0xffffffff;
repl->valid_hooks = 0x1;
repl->num_entries = 0x1;
ret = setsockopt(sock, SOL_IP, IPT_SO_SET_REPLACE, (void *) data, size);
printf("\ndone %d\n", ret);
perror("error: ");
return 0;
}
this is the output :
sock:3
data:
size:92
done -1
error: : Protocol not available
Looking briefly at the kernel code, this would seem to indicate that the IP tables module isn't available (i.e. the kernel wasn't built with it configured, or it can't be found or loaded).
It appears to me that for a socket of the kind you created, the code flow is:
enter raw_setsockopt: level != SOL_RAW so...
call ip_setsockopt: level == SOL_IP but option isn't any of the IP_xxx options so...
call nf_setsockopt: Search loaded netfilter modules for one that has registered IPT_SO_SET_REPLACE.
I think the last must have failed, so you get ENOPROTOOPT back (== Protocol not available)

Linux: unable to retrieve process name from pid via ioctl

I'm trying to retrieve retrieve process name from pid via ioctl, this is the C code:
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/signal.h>
#include <sys/syscall.h>
#include <sys/procfs.h>
#include <stdio.h>
#include <signal.h>
#include <elf.h>
#include <stdlib.h>
#include <errno.h>
int main(int argc, char **argv) {
char ProcID[50]="/proc/";
int fd;
prpsinfo_t ProcessInfo;
int ioctlResult;
if ( argc != 2 ) {
printf("usage: %s <pid>\n", argv[0]);
return 0;
}
strcat(ProcID,argv[1]);
fd = open(ProcID, O_RDONLY, 0);
if (fd == -1) {
printf("open error: [%d] [%s]\n",errno, strerror(errno));
return 0;
}
ioctlResult = ioctl(fd, NT_PRPSINFO, &ProcessInfo);
if (ioctlResult == -1)
{
printf("Error ioctl: [%d] [%s]\n",errno, strerror(errno));
} else {
printf("Process name: %s\n",ProcessInfo.pr_fname);
}
close(fd);
return 0;
}
When I try to execute it I obtain errno 25 (Inappropriate ioctl for device). I think the file descriptor open on "/proc/" isn't correct; is there another path to consider ?

Linux sockets communicating with QTcpSockets in Qt 4

I am trying to communicate with TCP between a Qt program and a regular linux program. I have an existing linux client server program and I am trying to replace the server program with a Qt application. Here is the linux client code
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
int main(int argc, char *argv[])
{
int sockfd, portno, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
portno = 9876;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
{
printf("ERROR opening socket");
return -1;
}
server = gethostbyname("localhost");
if (server == NULL)
{
printf("ERROR, no such host\n");
return -1;
}
memset((char *) &serv_addr,0,sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(portno);
connect(sockfd,(sockaddr*)&serv_addr,sizeof(serv_addr));
sprintf(buffer,"This is a test\n");
n = write(sockfd,buffer,256);
return 0;
}
Here is the qt code
#include <Qt>
#include <QApplication>
#include <QTcpServer>
#include <QMessageBox>
#include <QTcpSocket>
#include <QtNetwork>
#include "qtserver.h"
Server::Server()
{
tcp = new QTcpServer(this);
tcp->listen(QHostAddress::Any,9876);
QObject::connect(tcp,SIGNAL(newConnection()),this,SLOT(printline()));
}
void Server::printline()
{
QTcpSocket *client = tcp->nextPendingConnection();
QObject::connect(client,SIGNAL(disconnected()),
client,SLOT(deleteLater()));
QDataStream in(client);
in.setVersion(QDataStream::Qt_4_0);
QString data;
in >> data;
printf("String = %s\n",(char*)data.data());
}
int main(int argc,char** argv)
{
QApplication a(argc,argv);
Server* server = new Server();
return a.exec();
}
When i try to run both of them I just get "String = " instead of the string outputting. Any idea what I'm doing wrong?
QString::data() returns QChar*, you can't just cast it to char* and hope that it would always work. For debugging QString, use qPrintable instead.
Also, QTcpSocket is very easy to use. Still, instead of writing the code from scratch, why not start by checkout out the examples, e.g. Fortune Server example.

Resources