start and terminate cu with a C program - c

I'm trying to communicate with another UNIX device via ttyS0 using cu (google "cu unix" to find out more about cu). My program works perfectly fine, but the problem is, that after the first execution of the program (establish connection, read logfiles and some other stuff) the terminal is not accessible anymore. I've just posted the core of my problem in a simplified version of the code where I'm only focussing on the actual question that I have:
When I'm doing these commands by hand "cu -l /dev/ttyS0 -s 115200" and "~." (just like in the man pages of cu: ~. terminates the connection) everything works fine. A sequential program like
system("cu -l /dev/ttyS0 -s 115200");
system("~.");
isn't working, because cu is still active, and nothing is executed after that....the program just sits there waiting for cu... same thing would happen in a simple bash script... cu would be preventing the program/script from proceeding - that's why I'm using threads, and like I said, my actual program works, but the program isn't terminating like I want it to and the Terminal has to be restarted.
When I execute the following program, I only get
Connected
sh: ~.: not found
pressing enter
cu: can't restore terminal: Input/Output error
Disconnected
and an unusable terminal is left open (can't type or do anything with it)...
#define _BSD_SOURCE
#include <termios.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <time.h>
#include <stdlib.h>
#include <pthread.h>
void first(){
system("cu -l /dev/ttyS0 -s 115200");
pthread_exit(NULL);
}
void second(){
system("~."); //also "~.\n" isn't changing anything
pthread_exit(NULL);
int main(){
pthread_t thread1, thread2;
pthread_create ( &thread1, NULL, (void*)first, NULL );
sleep(3);
pthread_create ( &thread2, NULL, (void*)second, NULL );
sleep(4);
exit(0);
return 0;
}

When you do it by hand, the ~. you're typing is not taken as a system command, but as input for the cu process that's still running. Best proof is that you didn't have a shell prompt at that time.
So the equivalent is not to do another system("~.") but to pass those characters as input to the first system("cu ...").
For instance:
system("echo '~.' | cu ....");
Obviously this doesn't allow you to open a "cu" connection and send the "~." at a later time. If you wish to do that, I suggest you take a look at the popen command (man 3 popen). This will start a cu process, and leave you with a file descriptor into which you can write your ~. at a later time.

Related

setuid not working, linux rhel6, simple example

This is a repost after being referred to "Calling a script from a setuid root C program - script does not run as root" for a solution
My problem is different in that I do not want to run the C program (and c-shell script called inside) as root. Rather, I want to run as the owner of the c program file.
Also, I tried with "setuid(0)" as this was the solution in the referenced post. This is reflected in the edited code below. Same results.
Also, I opened permissions up all the way this time with "chmod 7775" (just in case it was a permissions problem)
Here's the original note with edits to reflect the change to "setuid(0)"
I'm having a problem implementing an simple example that would demonstrate how setuid can be made to run a binary with the uid of the file owner of the binary. What I would eventually like to do is run a c-shell script using this technique.
I read that this will not work for shell scripts but also heard of a work-around using a C program to run a system() call that'll run the c-shell script ( e.g. system("source my.csh") ). I wrote a C program that attempts this, plus simply reports the current uid. This is what I tried...
From my current shell, I did a "su katman" to become the user of the binary I want to run as user katman.
I created a C program try.c. ...
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
setuid(0);
printf("In try.c ... sourcing katwhoami.csh...\n");
system( "source /home/me/su_experiments/katwhoami.csh");
printf("In try.c ... using straight system call...\n");
system("whoami");
return 0;
}
I "setuid(0)" as recommended by a reference to a different note. But earlier, I tried setting it to the uid of the C program's owner as obtained with "id -u".
The katwhoami.csh shell script is simply...
date
echo "In katwhoami.csh, I am "`whoami`
echo "In katwhoami.csh, I am "$USER
exit
Then I compiled the C program and set the bit...
% gcc -o try try.c
% chmod 7775 try
% ls -l try
-rwsrwsr-x 1 katman design 6784 Mar 1 11:59 try
And then I test it...
% try
In try.c ... sourcing katwhoami.csh...
Thu Mar 1 12:28:28 EST 2018
In katwhoami.csh, I am ktadmin
In katwhoami.csh, I am ktadmin
In try.c ... using straight system call...
ktadmin
...which is what I expected.
I exit to get back to the shell I started from, hoping that if I run try there, it'll tell me I'm "katman"....
% exit
% whoami
daveg
% try
In try.c ... sourcing katwhoami.csh...
Thu Mar 1 12:30:04 EST 2018
In katwhoami.csh, I am daveg
In katwhoami.csh, I am daveg
In try.c ... using straight system call...
daveg
... which is not what I was hoping for :-(
As you can probably tell, I'm new at using this.
Any help would be appreciated !
Update....
I tried a new sample program, a.c...
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fh;
setuid(1234);
system("whoami");
fh=fopen("test.file","w");
fprintf(fh,"Here I am\n");
fclose(fh);
return 0;
}
I compiled and set the bit
gcc -o a a.c
chmod 4775 a
Then I exited the "su" and ran as a user that is NOT the owner of the binary. Same result as before with regard to reported uid (the current uid), BUT, the owner of the file that the C program created ion this version was the owner of the C program !!! So that worked.
Is there something fishy about the "whoami" command? system() call ?
If I do a "system("source some.csh") does it create a new shell which assumes the original uid (not the owner of the C binary) ? Something like that ?
I really need the new uid to "stick" as far as child processes.

open system call - Linux

Trying to open tty port using open system call. HOw do i know if this port is being used by another application in case the open system call returns -1?
DO not find error codes for the same.
a call to open() won't give you an error if the file is already open.
Howerver, you can try to analyze the output of the linux lsofcommand:
lsof /dev/ttyS0
It will return information about the processes that opened the given file (in this case: /dev/ttyS0).
(I've tested this a few times so I'm not sure about it, but lsof seems to return 0 if the file is opened by a process and return 1 if no process has opened it. This could be an indication, however I would suggest you really analyze the output of the command itself)
#include <errno.h>
#include <stdio.h>
#include <strcing.h>
int main()
{
if(open("/dev/ttyS0", O_RDWR))
printf("errno = %s\n", strerror(errno));
return errno;
}
see this link in order to figure out what the error code is.

Execute command just before Mac going to sleep

I wrote a C program/LaunchDaemon that checks if my MacBook is at home (connected to my WLAN). If so, it disables my password protection; if not, it enables it.
Easy. But the problem is that when I take my MacBook anywhere else and password protection is disabled, it will wake up without a password protection.
My fix for this would be: enable the password protection every time just before it goes to sleep.
QUESTION: is there any way find out when my Mac is preparing for sleep? Some interupt I can let my program listen to?
You can do it using I/O Kit, check Apple's QA1340: Registering and
unregistering for sleep and wake notifications. You may also want to
analyze the SleepWatcher utility sources or use/integrate for your needs.
From the homepage:
SleepWatcher 2.2 (running with Mac OS X 10.5 to 10.8, source code included)
is a command line tool (daemon) for Mac OS X that monitors sleep, wakeup and
idleness of a Mac. It can be used to execute a Unix command when the Mac or
the display of the Mac goes to sleep mode or wakes up, after a given time
without user interaction or when the user resumes activity after a break or
when the power supply of a Mac notebook is attached or detached. It also can
send the Mac to sleep mode or retrieve the time since last user activity. A
little bit knowledge of the Unix command line is required to benefit from
this software.
I attach below the contents of my C file beforesleep.c which executes some command line commands (in my case shell commands and AppleScript scripts) when a "will sleep" notification is received.
Where you can put your code:
In order to run your code when the mac is going to sleep, just replace the system(...) calls with the code you wish to run.
In my case, I use system() as it allows me to run shell commands passed as strings, but if you prefer to run just C code instead, you can just put your C code there.
How to build it
In order to build this file, I run:
gcc -framework IOKit -framework Cocoa beforesleep.c
Remark
If you are going to use this code, make sure it is always running in background. For example, I have a Cron job which makes sure that this code is always running, and it launches it again in case it is accidentally killed for any reason (although it never happened to me so far). If you are experienced enough, you can find smarter ways to ensure this.
Further info
See this link (already suggested by sidyll) for more details about how this works.
Code template
#include <ctype.h>
#include <stdlib.h>
#include <stdio.h>
#include <mach/mach_port.h>
#include <mach/mach_interface.h>
#include <mach/mach_init.h>
#include <IOKit/pwr_mgt/IOPMLib.h>
#include <IOKit/IOMessage.h>
io_connect_t root_port; // a reference to the Root Power Domain IOService
void
MySleepCallBack( void * refCon, io_service_t service, natural_t messageType, void * messageArgument )
{
switch ( messageType )
{
case kIOMessageCanSystemSleep:
IOAllowPowerChange( root_port, (long)messageArgument );
break;
case kIOMessageSystemWillSleep:
system("/Users/andrea/bin/mylogger.sh");
system("osascript /Users/andrea/bin/pause_clockwork.scpt");
IOAllowPowerChange( root_port, (long)messageArgument );
break;
case kIOMessageSystemWillPowerOn:
//System has started the wake up process...
break;
case kIOMessageSystemHasPoweredOn:
//System has finished waking up...
break;
default:
break;
}
}
int main( int argc, char **argv )
{
// notification port allocated by IORegisterForSystemPower
IONotificationPortRef notifyPortRef;
// notifier object, used to deregister later
io_object_t notifierObject;
// this parameter is passed to the callback
void* refCon;
// register to receive system sleep notifications
root_port = IORegisterForSystemPower( refCon, &notifyPortRef, MySleepCallBack, &notifierObject );
if ( root_port == 0 )
{
printf("IORegisterForSystemPower failed\n");
return 1;
}
// add the notification port to the application runloop
CFRunLoopAddSource( CFRunLoopGetCurrent(),
IONotificationPortGetRunLoopSource(notifyPortRef), kCFRunLoopCommonModes );
/* Start the run loop to receive sleep notifications. Don't call CFRunLoopRun if this code
is running on the main thread of a Cocoa or Carbon application. Cocoa and Carbon
manage the main thread's run loop for you as part of their event handling
mechanisms.
*/
CFRunLoopRun();
//Not reached, CFRunLoopRun doesn't return in this case.
return (0);
}

named pipe windows behaves

I'm trying to create a basic server with a named pipe in windows. The problem occurs when trying to connect the pipes(I suspect).
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
int main(){
HANDLE p1, p2;
printf("Server...");
p1 = CreateNamedPipe(TEXT("\\\\.\\PIPE\\pipe1"),PIPE_ACCESS_INBOUND,PIPE_TYPE_BYTE|PIPE_WAIT,3,0,0,0,NULL);
p2 = CreateNamedPipe(TEXT("\\\\.\\PIPE\\pipe2"),PIPE_ACCESS_OUTBOUND,PIPE_TYPE_BYTE|PIPE_WAIT,3,0,0,0,NULL);
if(p1 == INVALID_HANDLE_VALUE || p2 == INVALID_HANDLE_VALUE ) { printf("pipe fail");exit(2);}
printf("1. Pipes created");
ConnectNamedPipe(p1,NULL);
ConnectNamedPipe(p2,NULL);
printf("2. Pipes connected");
DisconnectNamedPipe(p1);
DisconnectNamedPipe(p2);
CloseHandle(p1);
CloseHandle(p2);
printf("3. Pipes disconnected & closed");
printf("exit server...");
return 0;
}
When running the program, it doesn't print anything and when i manually stop it it just prints
Server...1. Pipes created (in my IDE console - Eclipse) or if I run program directly it, it prints the same then it holds.
It takes two to tango here. You'll need to write another program that calls CreateFile() to open the named pipe. Only then will the ConnectNamedPipe() call in your server program complete. Avoid using two pipes in your test program, pipes are bi-directional so you only need a single pipe to talk back-and-forth. If you want to support multiple clients then simply call ConnectNamedPipe again after a pipe connection was established. At which point it also becomes important to use overlapped I/O or threads.
Do take a look at the sample code included in the MSDN articles for named pipes. It shows you how to write both the server and client code.

Running daemon through rsh

I want to run program as daemon in remote machine in Unix. I have rsh connection and I want the program to be running after disconnection.
Suppose I have two programs: util.cpp and forker.cpp.
util.cpp is some utility, for our purpose let it be just infinite root.
util.cpp
int main() {
while (true) {};
return 0;
}
forker.cpp takes some program and run it in separe process through fork() and execve():
forker.cpp
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
int main(int argc, char** argv) {
if (argc != 2) {
printf("./a.out <program_to_fork>\n");
exit(1);
}
pid_t pid;
if ((pid = fork()) < 0) {
perror("fork error.");
exit(1);
} else if (!pid) {
// Child.
if (execve(argv[1], &(argv[1]), NULL) == -1) {
perror("execve error.");
exit(1);
}
} else {
// Parent: do nothing.
}
return 0;
}
If I run:
./forker util
forker is finished very quickly, and bash 'is not paused', and util is running as daemon.
But if I run:
scp forker remote_server://some_path/
scp program remote_server://some_path/
rsh remote_server 'cd /some_path; ./forker program'
then it is all the same (i.e. at the remote_sever forker is finishing quickly, util is running) but my bash in local machine is paused.
It is waiting for util stopping (I checked it. If util.cpp is returning than it is ok.), but I don't understand why?!
There are two questions:
1) Why is it paused when I run it through rsh?
I am sure that I chose some stupid way to run daemon. So
2) How to run some program as daemon in C/C++ in unix-like platforms.
Tnx!
1) Why is it paused when I run it through rsh?
When you fork a process, the child process has its own copy of the parent's file descriptors. Each of the child's file descriptors refers to the same open file description with the corresponding file descriptor of the parent. After you call fork() you are not closing the standard streams (stdin, stdout, stderr) in the child process before your call to execve() so they are still connected to rsh. It may be the case that rsh will not return as long as any process on the remote server is holding a reference to these streams. You could try closing the standard streams using fclose() before your call to execve() or redirect them when you execute your forker program (i.e. ./forker program >/dev/null 2>/dev/null </dev/null).
2) How to run some program as daemon in C/C++ in unix-like platforms.
According to wikipedia, nohup is most often used to run commands in the background as daemons. There are also several daemon related questions on this site you can refer to for information.
From wikipedia:
nohup is a POSIX command to ignore the HUP (hangup) signal, enabling the command to keep running after the user who issues the command has logged out. The HUP (hangup) signal is by convention the way a terminal warns depending processes of logout.
If your program will always run as a daemon, you can look into the possibility of calling daemon() from within your program. The daemon() convenience function exists in some UNIX systems.
From the daemon(3) man page:
The daemon() function is for programs wishing to detach themselves from the controlling terminal and run in the background as system daemons.
Should this function not exist for you or should there be instances where your program does not run as a daemon, your forker program can also be modified to 'daemonize' your other program.
Without making any changes to your code, you could try something like the following:
rsh remote_server 'cd /some_path; nohup ./forker program >program.out 2>program.err </dev/null &'

Resources