How to get windows size from Linux - c

everyone. I am still new to programming. I really need some help about the issues that I'm facing. So, the situation here is I'm trying to display a warning when the terminal size is below 80x24. For the record, my Os is Window, but I'm using a virtual machine to run Linux because all the files are in Linux. When i run the file using terminal, the warning display correctly. But the problem is when i try to run the file from Windows using PuTTY. The warning did not appear. I'm sure its because the function that I'm using can only read the Linux environment and not the Windows. Can anyone help me or point me to a direction on how to make it capable of getting the dimension of windows. The files should all remain in Linux. I am using C.
Here are just some part of the code to show about displaying warning and getting dimension.
//This is to display warning
int display_warning()
{
CDKSCREEN *cdkscreen = 0;
WINDOW *cursesWin = 0;
char *mesg[5];
char *buttons[] = {"[ OK ]"};
CDKDIALOG *confirm;
cursesWin = initscr();
cdkscreen = initCDKScreen (cursesWin);
initCDKColor();
mesg[0] = "</2>"The size of Window must be at least 80x24.";
confirm = newCDKDialog(cdkscreen, CENTER, CENTER, mesg, 1, buttons, A_REVERSE, TRUE,TRUE, FALSE);
setCDKDialogBackgroundColor(confirm, "</2>");
injectCDKDialog(confirm,TAB);
activateCDKDialog(confirm,0);
if (confirm -> exitType == vNORMAL){
destroyCDKDialog (confirm);
destroyCDKScreen (cdkscreen);
endCDK();
}
return 0;
}
//This is to get the dimension
int get_terminal_size()
{
int cols;
int lines;
#ifdef TIOCGSIZE
struct ttysize ts;
ioctl(0,TIOCGSIZE, &ts);
lines = ts.ts_linesl;
cols = ts.ts_cols;
#elif defined(TIOCGWINSZ)
struct winsize ts;
ioctl(0, TIOCGWINSZ, &ts);
lines = ts.ws_row;
cols = ts.ws_col;
#endif
if((lines <= 23)||(cols <= 79)){
display_warning();
}
return 0;
}
//then there will be the main function that i think is not necessary to put the code here.
All comment and help are very appreciated. I am a beginner in programming, so please excuse me if there are some basic things that i dont know.
Fikrie

The issue has nothing to do with PuTTY per se, and everything to do with SSH clients and pseudoterminals in general.
To avoid this issue, configure your PuTTY to use a pseudoterminal. (In the TTY panel, there is a "Don't allocate a pseudoterminal" checkbox. Make sure it is not checked.)
With ssh, you need to use the -t option to tell ssh to use a pseudoterminal.
Here is a simple example program you can use in Linux to obtain the terminal size. It does not require curses:
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <stdio.h>
static int get_size(const int fd, int *const rows, int *const cols)
{
struct winsize sz;
int result;
do {
result = ioctl(fd, TIOCGWINSZ, &sz);
} while (result == -1 && errno == EINTR);
if (result == -1)
return errno;
if (rows)
*rows = sz.ws_row;
if (cols)
*cols = sz.ws_col;
return 0;
}
int main(void)
{
int rows, cols;
if (!get_size(STDIN_FILENO, &rows, &cols) ||
!get_size(STDOUT_FILENO, &rows, &cols) ||
!get_size(STDERR_FILENO, &rows, &cols))
printf("%d rows, %d columns\n", rows, cols);
else
fprintf(stderr, "Terminal size is unknown.\n");
return 0;
}
The actual information is obtained using the TIOCGWINSZ TTY ioctl.
The pseudoterminal size is actually maintained by the kernel. If there is no pseudoterminal, just standard streams, there are no rows and columns; it's just a stream in that case. In particular, even tput lines and tput cols will fail then.
Many interactive command-line programs will refuse to work if there is no pseudoterminal. For example, top will report something like "TERM environment variable not set" or "top: failed tty get". Others will work, just not interactively; they'll output once only, but as if the terminal was infinitely tall and infinitely wide.
In summary, your application should recognize whether it is running in a pseudoterminal (with terminal size known, curses support possible, and so on), or in stream mode (via SSH or PuTTY, deliberately without a pseudoterminal -- or perhaps just because inputs and outputs are all directed to/from files or some such).

Related

Why does `ioctl(fd, EVIOCGRAB, 1)` cause key spam sometimes?

I'm trying to write my own "keyboard driver" (without actually writing a kernel module),
by grabbing the keyboard at what I assume is the lowest level of abstraction in userland: /dev/input/event*.
The following code does the grabbing, provided you change the first ocurrence of ioctl(fd, EVIOCGRAB, UNGRAB)
to ioctl(fd, EVIOCGRAB, GRAB).
// gcc main.c -o main
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <linux/input.h>
#include <fcntl.h>
#include <errno.h>
#define EXIT_KEY KEY_ESC
#define UNGRAB 0
#define GRAB 1
const char* kbd_device = "/dev/input/event4";
// ------------------------------------------------------------------------------------------------
int main(void){
int fd = open(kbd_device, O_RDONLY);
if(fd == -1){
printf("Cannot open %s. %s.\n", kbd_device, strerror(errno));
return -1;
}
if(ioctl(fd, EVIOCGRAB, UNGRAB))
printf("Couldn't grab %s. %s.\n", kbd_device, strerror(errno));
else
printf("Grabbed %s!\n", kbd_device);
while(1){
struct input_event event;
read(fd, &event, sizeof(event));
if (event.type == EV_KEY && event.value >= 0 && event.value <= 2){
printf("%d %3d\n", event.value, event.code);
if(event.code == EXIT_KEY){
ioctl(fd, EVIOCGRAB, UNGRAB);
close(fd);
return 0;
}
}
}
}
Problem
If I run gcc main.c -o main && sudo ./main, everything works as expected.
If first compile and then I run sudo ./main, however, the terminal scrolls down nonstop, as if the RETURN key was held down.
Why does happen?
Notes
I'm running Ubuntu 14.04
On my platform, /dev/input/event4 happens to be the keyboard
Motivation
I'm trying to write a keyboard "driver" that works both on X and not on X (eg. a TTY).
I understand X11's keyboard library/extension is XKB. I think the TTY's keyboard library is linux/divers/tty/vt/keyboard.c (source),
the initial keyboard map it uses is in linux/drivers/tty/vt/defkeymap.map (source), and it can be modified by using loadkeys (source here). Do correct me if I'm wrong.
When you type
gcc main.c -o main && sudo ./main ↵
GCC takes some time, so the ↵ key has been released by the time ./main runs.
When you type
sudo ./main ↵
the terminal sends the shell a newline as soon as you push down ↵, and starts executing ./main. Then the ↵ released event is seen by your program, but not by your terminal, because your program has grabbed the input device. Thus, to the terminal it looks like ↵ is stuck down, so it continues to produce newlines.
This question has been answered already, but it still lacks an elegant solution to the problem.
I had the same issue with a driver I implemented some time ago that also required capturing the keyboard.
I could not find a way to force the the kernel to recognize a key release in the device before capturing it, so the solution consists in not grabbing the device until you detect that all keys have actually been released. This can be accomplished by monitoring the device with the EVIOCGKEY ioctl AFTER opening it and BEFORE grabbing it.
OBS: Please observe that the apparently dummy read function within the while loop is necessary in order to avoid a busy wait and so that the loop will iterate after each event from the input device. Also note that the file descriptor must be configured for blocking I/O (the default).
void waitReleaseAll(int fd) {
struct input_event evt;
unsigned char key_b[KEY_MAX/8 + 1];
int i, nothing;
while ( 1 ) {
memset(key_b, 0, sizeof(key_b));
ioctl(fd, EVIOCGKEY(sizeof(key_b)), key_b);
for ( nothing = 1 , i = 0 ; i < KEY_MAX/8 + 1 ; i++ ) {
if ( key_b[i] != 0 ) { nothing = 0; break; }
}
if ( nothing ) break;
read(fd, &evt, sizeof(evt));
}
printf("All keys are now released\n");
}
To fix your problem, you should use SIGINT in your code to identify Ctrl-C keystroke from the user.
Implement SIGNAL in your code:
static volatile sig_atomic_t stop = 0;
static void interrupt_handler(int sig)
{
stop = 1;
} // Outside of the main function.
int main(int argc, char *argv[])
{
signal(SIGINT, interrupt_handler);
while (!stop) {
//your code
}
exit(0);
}

Accessing Keys from Linux Input Device

What I am trying to do
So, I have been trying to access keyboard input in Linux. Specifically, I need to be able to access modifier key presses without other keys being pressed. Furthermore, I want to be able to do this without an X system running.
So, in short, my requirements are these:
Works on Linux
Does not need X11
Can retrieve modifier key press without any other keys being pressed
This includes the following keys:
Shift
Control
Alt
All I need is a simple 0 = not pressed, 1 = currently pressed to let me know if
the key is being held down when the keyboard is checked
My computer setup
My normal Linux machine is on a truck towards my new apartment; so, I only have a Macbook Air to work with right now. Therefore, I am running Linux in a VM to test this out.
Virtual Machine in VirtualBox
OS: Linux Mint 16
Desktop Environment: XFCE
Everything below was done in this environment. I've tried both with X running and in one of the other ttys.
My Thoughts
I'll alter this if someone can correct me.
I've done a fair bit of reading to realize that higher-level libraries do not provide this kind of functionality. Modifier keys are used with other keys to provide an alternate key code. Accessing the modifier keys themselves through a high-level library in Linux isn't as easy. Or, rather, I haven't found a high-level API for this on Linux.
I thought libtermkey would be the answer, but it doesn't seem to support the Shift modifier key any better than normal keystroke retrieval. I'm also not sure if it works without X.
While working with libtermkey (before I realized it didn't get shift in cases like Shift-Return), I was planning to write a daemon that would run to gather keyboard events. Running copies of the daemon program would simply pipe requests for keyboard data and receive keyboard data in response. I could use this setup to have something always running in the background, in case I cannot check key code statuses at specific times (have to be receive key codes as they happen).
Below are my two attempts to write a program that can read from the Linux keyboard device. I've also included my small check to make sure I had the right device.
Attempt #1
I have tried to access the keyboard device directly, but am encountering issues. I have tried the suggestion here that is in another Stack Overflow thread. It gave me a segmentation fault; so, I changed it from fopen to open:
// ...
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-0-event-kbd", O_RDONLY);
char key_map[KEY_MAX/8 + 1];
memset(key_map, 0, sizeof(key_map));
ioctl(fd, EVIOCGKEY(sizeof key_map), key_map);
// ...
While there was no segmentation fault, there was no indicator of any key press (not just modifier keys). I tested this using:
./foo && echo "TRUE" || echo "FALSE"
I've used that to test for successful return codes from commands quite a lot; so, I know that's fine. I've also outputted the key (always 0) and mask (0100) to check. It just doesn't seem to detect anything.
Attempt #2
From here, I thought I'd try a slightly different approach. I wanted to figure out what I was doing wrong. Following this page providing a snippet demonstrating printing out key codes, I bundled that into a program:
#include <stdio.h>
#include <stdint.h>
#include <string.h>
#include <fcntl.h>
#include <linux/input.h>
int main(int argc, char** argv) {
uint8_t keys[128];
int fd;
fd = open("/dev/input/by-path/platform-i8042-serio-event-kbd", O_RDONLY);
for (;;) {
memset(keys, 0, 128);
ioctl (fd, EVIOCGKEY(sizeof keys), keys);
int i, j;
for (i = 0; i < sizeof keys; i++)
for (j = 0; j < 8; j++)
if (keys[i] & (1 << j))
printf ("key code %d\n", (i*8) + j);
}
return 0;
}
Previously, I had the size to 16 bytes instead of 128 bytes. I should honestly spend a bit more time understanding ioctl and EVIOCGKEY. I just know that it supposedly maps bits to specific keys to indicate presses, or something like that (correct me if I'm wrong, please!).
I also didn't have a loop initially and would just hold down various keys to see if a key code appeared. I received nothing; so, I thought a loop might make the check easier to test in case a missed something.
How I know the input device is the right one
I tested it by running cat on the input device. Specifically:
$ sudo cat /dev/input/by-path/platform-i8042-serio-0-event-kbd
Garbage ASCII was sent to my terminal on key press and release events starting with the return (enter) key when I began the output using cat. I also know that this seems to work fine with modifier keys like shift, control, function, and even Apple's command key on my Macbook running a Linux VM. Output appeared when a key was pressed, began to appear rapidly from subsequent signals sent by holding the key down, and outputted more data when a key was released.
So, while my approach may not be the right one (I'm willing to hear any alternative), the device seems to provide what I need.
Furthermore, I know that this device is just a link pointing to /dev/input/event2 from running:
$ ls -l /dev/input/by-path/platform-i8042-serio-0-event-kbd
I've tried both programs above with /dev/input/event2 and received no data. Running cat on /dev/input/event2 provided the same output as with the link.
Open the input device,
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <linux/input.h>
#include <string.h>
#include <stdio.h>
static const char *const evval[3] = {
"RELEASED",
"PRESSED ",
"REPEATED"
};
int main(void)
{
const char *dev = "/dev/input/by-path/platform-i8042-serio-0-event-kbd";
struct input_event ev;
ssize_t n;
int fd;
fd = open(dev, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "Cannot open %s: %s.\n", dev, strerror(errno));
return EXIT_FAILURE;
}
and then read keyboard events from the device:
while (1) {
n = read(fd, &ev, sizeof ev);
if (n == (ssize_t)-1) {
if (errno == EINTR)
continue;
else
break;
} else
if (n != sizeof ev) {
errno = EIO;
break;
}
The above snippet breaks out from the loop if any error occurs, or if the userspace receives only a partial event structure (which should not happen, but might in some future/buggy kernels). You might wish to use a more robust read loop; I personally would be satisfied by replacing the last break with continue, so that partial event structures are ignored.
You can then examine the ev event structure to see what occurred, and finish the program:
if (ev.type == EV_KEY && ev.value >= 0 && ev.value <= 2)
printf("%s 0x%04x (%d)\n", evval[ev.value], (int)ev.code, (int)ev.code);
}
fflush(stdout);
fprintf(stderr, "%s.\n", strerror(errno));
return EXIT_FAILURE;
}
For a keypress,
ev.time: time of the event (struct timeval type)
ev.type: EV_KEY
ev.code: KEY_*, key identifier; see complete list in /usr/include/linux/input.h
ev.value: 0 if key release, 1 if key press, 2 if autorepeat keypress
See Documentation/input/input.txt in the Linux kernel sources for further details.
The named constants in /usr/include/linux/input.h are quite stable, because it is a kernel-userspace interface, and the kernel developers try very hard to maintain compatibility. (That is, you can expect there to be new codes every now and then, but existing codes rarely change.)

Get in which terminal column I'm writing

In my C program I would like to know where my cursor is located in terminal. For example, another program could have written something before mine and I would like to know how much space is left before the last column of the terminal, or I could not know the terminal reaction to some special sequences (like colors: I could write it but they are not showed).
Any suggestion?
Edit: it would be better avoiding over complicated solutions like ncurses (ncurses doesn't know where's the cursor directly: it computes its position).
Edit 2: I found a way to do it, but it works only in non-graphical terminals: https://www.linuxquestions.org/questions/programming-9/get-cursor-position-in-c-947833/
Edit 3: Nice code and it works well, but it uses /dev/vcsaN (same problem of Edit 2): http://dell9.ma.utexas.edu/cgi-bin/man-cgi?vcs+4
Ncurses is a big and powerful library for creating terminal-based text interfaces.
tputs is a simple low-level universal function for manipulating terminal capabilities.
Either one could serve your needs.
You could try using ncurses' getyx().
This solution is not optimal because it refers to /dev/vcsa*. Hope this could help someone else.
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
int main(void)
{
int fd;
char *device = "/dev/vcsa2";
struct {unsigned char lines, cols, x, y;} scrn;
fd = open(device, O_RDWR);
if (fd < 0) {
perror(device);
exit(EXIT_FAILURE);
}
(void) read(fd, &scrn, 4);
printf("%d %d\n", scrn.x, scrn.y);
exit(EXIT_SUCCESS);
}
Generally you are supposed to remember where you've left the cursor.
However, most terminals do respond to DSR; Device Status Request. By sending
CSI 6 n
you'll receive a CPR; cursor position report, in the form of
CSI Pl;Pc R
where Pl and Pc give the cursor line and column number, indexed from 1.

Writing a command line shell with C; trying to use ncurses/C for the first time

I'm working on a class project in which I must write a command line shell with the following requirements:
The shell must able to read buffered input
Buffer should be 64 characters
Error conditions should be handled
Exceeded buffer size
Interruptions (when a signal arrives) – see the man page for read()
Invalid input (unparsable characters, blank lines, etc)
Any other error that may be encountered.
Shell must have a history of at least 20 items, and the history must not be of a static size. When the history buffer is full, the oldest item is removed and the newest item added.
Programs should be able to run in the foreground or background. (using &)
Ctrl-D will exit the shell
Ctrl-C will print the complete history
The Command ‘history’ will also print the complete history. Newest items will be at the bottom of the list.
All other signals will be trapped and displayed to the user in the shell
Program will use the read() command to read in input, unless the arrow keys are supported
I have opted to implement arrow keys for history cycling, so I'm using ncurses for input, rather than read(). I think I'm doing all right using strtok() to parse input, and fork() and execvp() to run the processes, but I'm not doing all right implementing ncurses correctly. All I've gotten it to do so far is init a new screen, display the prompt, then segfault upon any key press. Not good.
I reckon the problem must be in my design. I'm not wrapping my head around ncurses too well. What sort of data structures should I be using for this project? How should I handle the ncurses setup, teardown, and everything in between? What's the deal with windows and screens, and should I have a single globally accessible window/screen that I work with? Also, I've been trying to use a char* for the input buffer, and a char** for the command history, but I have no experience in C, so despite reading up on malloc, calloc, and realloc, I'm not sure of the best way to store commands in the buffer and the history. Any tips on managing these char arrays?
tl;dr: How do I use ncurses correctly to make a command line shell, and how do I handle the command memory management with C?
I realize this is a pretty hefty question. :(
edit: I have already seen http://www.gnu.org/software/libc/manual/html_node/Implementing-a-Shell.html and http://www.linuxinfor.com/english/NCURSES-Programming/ but the ncurses documentation has actually too much overhead. I just want to use its ability to recognize arrow keys.
Here's some sample code which:
Performs dynamic memory allocation.
Reads from the console in non-blocking mode.
Uses VT100 codes to print a frame buffer to the console.
It compiles on Linux using GCC without warnings or errors. It's far from bug free, but it should give you some ideas of what's possible. Compile and run it, pressing [up] and [down] will print messages, typing characters and hitting [enter] will "execute" the command.
#include <poll.h>
#include <signal.h>
#include <stdio.h>
#include <termios.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
/** VT100 command to clear the screen. Use puts(VT100_CLEAR_SCREEN) to clear
* the screen. */
#define VT100_CLEAR_SCREEN "\033[2J"
/** VT100 command to reset the cursor to the top left hand corner of the
* screen. */
#define VT100_CURSOR_TO_ORIGIN "\033[H"
struct frame_s
{
int x;
int y;
char *data;
};
static int draw_frame(struct frame_s *frame)
{
int row;
char *data;
int attrib;
puts(VT100_CLEAR_SCREEN);
puts(VT100_CURSOR_TO_ORIGIN);
for (row = 0, data = frame->data; row < frame->y; row++, data += frame->x)
{
/* 0 for normal, 1 for bold, 7 for reverse. */
attrib = 0;
/* The VT100 commands to move the cursor, set the attribute, and the
* actual frame line. */
fprintf(stdout, "\033[%d;%dH\033[0m\033[%dm%.*s", row + 1, 0, attrib, frame->x, data);
fflush(stdout);
}
return (0);
}
int main(void)
{
const struct timespec timeout = { .tv_sec = 1, .tv_nsec = 0 };
struct frame_s frame;
struct termios tty_old;
struct termios tty_new;
unsigned char line[128];
unsigned int count = 0;
int ret;
struct pollfd fds[1];
sigset_t sigmask;
struct tm *tp;
time_t current_time;
/* Set up a little frame. */
frame.x = 80;
frame.y = 5;
frame.data = malloc(frame.x * frame.y);
if (frame.data == NULL)
{
fprintf(stderr, "No memory\n");
exit (1);
}
memset(frame.data, ' ', frame.x * frame.y);
/* Get the terminal state. */
tcgetattr(STDIN_FILENO, &tty_old);
tty_new = tty_old;
/* Turn off "cooked" mode (line buffering) and set minimum characters
* to zero (i.e. non-blocking). */
tty_new.c_lflag &= ~ICANON;
tty_new.c_cc[VMIN] = 0;
/* Set the terminal attributes. */
tcsetattr(STDIN_FILENO, TCSANOW, &tty_new);
/* Un-mask all signals while in ppoll() so any signal will cause
* ppoll() to return prematurely. */
sigemptyset(&sigmask);
fds[0].events = POLLIN;
fds[0].fd = STDIN_FILENO;
/* Loop forever waiting for key presses. Update the output on every key
* press and every 1.0s (when ppoll() times out). */
do
{
fds[0].revents = 0;
ret = ppoll(fds, sizeof(fds) / sizeof(struct pollfd), &timeout, &sigmask);
if (fds[0].revents & POLLIN)
{
ret = read(STDIN_FILENO, &line[count], sizeof(line) - count);
if (ret > 0)
{
line[count + ret] = '\0';
if (strcmp(&line[count], "\033[A") == 0)
{
snprintf(frame.data, frame.x, "up");
count = 0;
}
else if (strcmp(&line[count], "\033[B") == 0)
{
snprintf(frame.data, frame.x, "down");
count = 0;
}
else if (line[count] == 127) // backspace
{
if (count != 0) { count -= ret;}
}
else if (line[count] == '\n')
{
snprintf(frame.data, frame.x, "entered: %s", line);
count = 0;
}
else
{
count += ret;
}
}
}
/* Print the current time to the output buffer. */
current_time = time(NULL);
tp = localtime(&current_time);
strftime(&frame.data[1 * frame.x], frame.x, "%Y/%m/%d %H:%M:%S", tp);
/* Print the command line. */
line[count] = '\0';
snprintf(&frame.data[(frame.y - 1) * frame.x], frame.x, "$ %s", line);
draw_frame(&frame);
}
while (1);
/* Restore terminal and free resources. */
tcsetattr(STDIN_FILENO, TCSANOW, &tty_old);
free(frame.data);
return (0);
}
If your input buffer is defined to be 64 characters, then I would recommend using a char array instead of a char*. Something like char input_buffer[65]; should serve your purposes (add an extra character for the trailing '\0').
As far as command history goes, you can use a two-dimensional array for that. Something like char command_history[20][65]; should let you store 20 old commands of 64 characters each.
Allocating these buffers statically should make things a bit easier for you, as you won't have to worry about malloc and friends.
It's hard to give you too much specific advice without seeing your code. I have a feeling that you are making the same type of mistakes that are typical to people first learning C. Can you post the part of your code that is giving you problems so that we can learn more about what you are doing?
Update after posted provided code:
One problem I'm seeing is that the function takeInput doesn't have a return statement. When you use input = takeInput(); inside your main function, the value of input isn't being set to what you think it is. It's probably not a valid pointer, which is causing your line that says input[j] to segfault.
Your usage of cmdHistory also needs revisiting. You allocate it with cmdHistory = (char**)calloc(21,sizeof(int));, which gives you enough space to store 21 integers. In the function printHistory, you pass elements of cmdHistory to printw as if they were strings (they're only integers). This is most definitely not doing what you want it to do. Instead, your allocation logic for cmdHistory needs to look more like your de-allocation logic (except backwards). Allocate an array of char**, then iterate through the array, assigning each pointer to a newly-allocated buffer. Just like you have one free statement for each element in the array plus a free for the array as a whole, you should have one malloc for each element plus one malloc for the array as a whole.
Even if you can't use a statically-allocated stack, try writing your program using one anyway. This will let you work the kinks out of your key detection logic, etc without having to worry about the dynamic memory part of the program. Once the rest of it is working, go back in and swap out the static memory for dynamic memory allocation. That way, you're only having to debug a little bit at a time.
Have you looked at the Readline library? It's ideal for use in your project.
http://cnswww.cns.cwru.edu/php/chet/readline/rltop.html

Format disk and create partition in C on LynxOS

Can you explain to me how I can do a mini program that does a system call in C in order to format the disk and create a new partition?
O/S is LynxOS.
Which commands would you execute at the shell?
Superficially, you could use some variant on this:
#include <stdlib.h>
static const char *cmds[] =
{
"command 1 with options",
"command 2 with different options",
0,
};
int main(void)
{
int i;
for (i = 0; cmds[i] != 0; i++)
if (system(cmds[i]) != 0)
exit(EXIT_FAILURE);
return(EXIT_SUCCESS);
}
I assume that the commands will provide appropriate diagnosis of any problems.
If you need to control the arguments, then you have more work to do.
The main caveat is "is this the disk that the o/s is running on", because if so, the chances are that the formatting of that disk will stop the programs from running successfully.

Resources