Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 4 years ago.
Improve this question
I'm making a Command-Line Operating system (command line interpreter). How to I get a line of input from the user?
I'm making a Command-Line Operating system. How to I get a line of input form a user?
The first things you'll need are some boot code (to get things like a memory map from firmware), physical memory management, virtual memory management, a scheduler and some kind of inter-process communication (IPC).
The next things you'll need is some kind of device enumeration framework, to help make a tree of devices to keep track of everything; followed by scanning PCI buses to add them to the tree of devices.
Next you'll want to tackle device resources - determining IO port ranges, memory mapped IO ranges and managing IRQs. This can be messy (e.g. AML interpreter for ACPI to determine IO APIC inputs, and "interrupt vector allocator" to handle MSI).
The next thing is USB controller drivers, USB hub driver and maybe (for obsolete hardware) a PS/2 controller driver. These all find devices connected to them (e.g. USB keyboard) and add them to the tree of devices, and then communicate with the drivers for those devices. At some point you might also want to worry about fault tolerance, power management and hot-plug (e.g. if a USB controller driver crashes, is put to sleep or is removed/unplugged; then you'd use the "tree of devices" to figure out which other drivers are effected).
Next, you'll want keyboard drivers. Specifically, a driver for "USB HID" (which is a single specification that covers all human input devices - keyboard, mouse, touchpad, joystick, ..), and maybe (for obsolete hardware) a PS/2 keyboard driver. Note that you'll probably also want an on-screen keyboard for touch-screen users, and input method editor/s to assist with input of some languages (Chinese, Japanese, Korean, etc).
Next, you'll want something for video output. Typically early boot code uses minimal "just enough to display boot log" code (if it's not hidden by a pretty splash image); but you'll want something that's actually good instead (likely including a font engine with Unicode support).
The end result of all of the above is that you'll have a set of (hopefully "standardised for your OS" and documented) device driver interfaces and all of the things that device drivers depend on; a way (the inter-process communication I mentioned near the start) to send "events" (key-presses) to a process and a way for processes to display output (draw things on the screen).
Once all that is done you can write a terminal emulation layer. This is a thing (process?) that hides all the nice modern stuff (e.g. OpenGL, events) under a layer of historic memorabilia (so that the end user's computer, which is likely to be capable of emulating realistic virtual reality environments, can be used as a glorified teleprinter from early last century). This also uses the inter-process communication I mentioned near the start (e.g. maybe pipes - stdin, stdout) to communicate with a child process.
Finally, you can begin writing some sort of command shell. This is just a process that communicates with its parent (e.g. with the terminal emulation layer) via. whatever you're using for inter-process communication (e.g. stdin, stdout) that allows users to start other processes and handles a little "forwarding" (e.g. while a child process is running, keyboard input that shell receives from terminal emulation layer gets forwarded by shell to its child process, and output the shell receives from its child gets forwarded by shell back to shell's parent/terminal emulator).
Note that as part of writing the command shell, or before writing the command shell, you might want to write some libraries to handle simple chores (e.g. getting a whole line of user input and handling things like "home", "end", "delete", "backspace", etc) so that these libraries can be used by all programs including the command shell itself.
It seems doubtful that you are truly implementing an operating system, but if you simply mean a command shell, then it might follow the following structure:
int main()
{
char command_line[1024] ;
char* input = NULL ;
int errorlevel = 0 ;
do
{
// Show command prompt
putchar( '>' ) ;
fflush( stdout ) ;
// Get command line
input = fgets( command_line, stdin, sizeof(command_line) ) ;
if( input != NULL )
{
// Process command line
errorlevel = parseCommand( input, &errorlevel ) ;
}
} while( input != NULL ) ;
return errorlevel ;
}
where parse parseCommand() is a function with the following interface:
int parseCommand( const char* cmd_line, const int* current_errorlevel ) ;
Here the answer to your question of how to get a line of user input is the fgets() function.
The complex part perhaps is in the implementation of parseCommand(); user input is the easy part, but make a start - have fun.
Unlike everyone I appreciate you thinking big but focus on the basics first as it is good to start small. Also, what you are doing is making a command line interpreter and not an OS. There's a big difference between the two. For an OS, you need a kernel, GUI, etc. However here's the solution to your query:
You can use gets, but you might receive a warning in this one
char *gets(char *str)
To overcome above limitation, we can use fgets as :
char *fgets(char *str, int size, FILE *stream)
Using %[^\n]%*c inside scanf
scanf(ā%[^\n]%*cā, str);
This one comes quite in handy when using for loop.
You have a bright future if you think innovatively (people lack this).
But it's always better to brush your base before going big. Welcome to stackoverflow :)
Related
I'm trying to write a Linux daemon that needs to take input from a keyboard-like (HID) device - it's not the console keyboard, but a second device (it's actually a 1D barcode scanner if it makes any difference). The daemon will process the data it receives ("keystrokes" from alphanumeric barcodes).
I know the daemon can use ioctl(EVIOCGRAB) to grab that device from /dev/input/eventx and then read() events (struct input_event from <linux/input.h>), that works, but it's too low level for my needs. I don't need to know about every up and down key event and I would rather not have to decode/handle simultaneous keys, i.e. I don't want to know KEY_DOWN+KEY_RTSHIFT, KEY_DOWN+KEY_A, KEY_UP+KEY_RTSHIFT, KEY_UP+KEY_A, I just want to receive "A".
Using the input events needs a whole pile of extra code to be written, just to get "A" out of it - and that seems a waste of time and effort when there are almost certainly existing keyboard handlers (or something like that) that will do a far better job than me hacking code together - I just can't find them!
Is there any way to put an existing layer of (keyboard?) software onto /dev/input/eventx that the daemon can then exclusively read a stream of simple ascii from?
For this device, /proc/bus/input/devices reports ...
H: Handlers=sysrq kbd leds event9
... which might suggest that something has already put a "kbd" layer on it, but how to access it?
If I don't EVIOCGRAB, then when I scan a barcode I see syslogs about "failed login on /dev/tty1", so that keyboard input is clearly trying to login to a terminal/shell somewhere :-/ (There's no X, desktop etc on this machine either.)
I am not aware of such library or daemon.
However, writing a daemon to do exactly that is not nearly as hard as you think. In my opinion/experience, if you do not need to implement autorepeat (that is, only do autorepeat if the keyboard-like device sends autorepeat keypresses), the daemon is surprisingly simple.
In particular, the main loop is just a blocking read followed by zero or more blocking writes, with an array look-up in the middle.
You can use either a named pipe (in which case you open the pipe before opening the device, because the open succeeds only after another process opens the named pipe or FIFO for reading), or a socket; either Unix Domain socket, or a TCP or UDP socket (on the loopback interface). I'd probably use a named pipe, /var/run/barcode-scanner.
I would use a separate configuration file for the input mapping, and I'd support the preprocessor macro names (KEY_) from /usr/include/linux/input-event-codes.h, parsed to an array using a helper awk script. The key mapping file would probably live in /etc/barcode-scanner/keymap, and contain definitions similar to
KEY_1 = 1
KEY_NUMERIC_1 = 1
KEY_E = e
shift KEY_E = E
ctrl KEY_E = \5
altgr KEY_E = ā¬
KEY_UP = \033[A
and so on. Events not listed in the definition file would be ignored or optionally logged.
You can use an array, because there are up to 768 (0 to KEY_MAX, inclusive; although 0 is KEY_RESERVED) different keyboard events; as a two-dimensional array, you'll probably want something like 16 arrays, for supporting all kombinations of Shift, Ctrl, Alt, and AltGr (or right alt key), when each key is pressed. Internally, you'll just need to handle KEY_LEFTSHIFT, KEY_RIGHTSHIFT, KEY_CAPSLOCK (to manage the shift state); KEY_LEFTALT (to manage the alt state); KEY_RIGHTALT (to manage the altgr state); and KEY_LEFTCTRL and KEY_RIGHTCTRL (to manage the ctrl state). If you use a bit mask to indicate the current states, you can use it as an index to the outer dimension of the lookup array. It really is very straightforward.
Note that each array element is then a string, that is emitted when a key of that state is pressed (ev.value == 1 for keypress, ev.value == 2 for autorepeat). Aside from the above special keys, you do not need to handle key releases at all.
Hm. I wonder if there are others who would need such a daemon? Would you use a GPL3-licensed one, if the sources were at GitHub?
The libevdev library is not exactly what you ask for. But it is widely used (e.g. by the Xorg server evdev and libinput drivers).
As state on the home page:
libevdev is essentially a read(2) on steroids for /dev/input/eventX devices.
It manages ioctl calls for you, handles an events queue, etc.
One additional feature you didn't ask for, but it is really helpful: it can handles events from multiple devices at once. It allows you to listen on multiple devices located in /dev/input and handle the same event type in a single thread.
I have been working on this 6502 emulator for a while, and I'm tying to get a simple Enhanced BASIC ROM to work. Although it lacks precise clock timing, the emulator did pass AllSuiteA.asm.
With EhBASIC, I've managed to get some output by printing the value of $F001 when a read is done to that address.
if(lastwrite == 0xF001)
{
printf("%c",CPUMEM[0xF001]);
}
However, I have no idea how to emulate the input process. This post states that whenever EhBASIC wants input, It will poll $F004. But my current code seems to have two problems:
while(1)
{
decodeandexecute();
if(lastread == 0xF004)
{
inputchar = getchar();
CPUMEM[0xF004] = inputchar;
}
if(lastwrite == 0xF001)
{
printf("%c",CPUMEM[0xF001]);
}
}
Input is only possible through individual letters (Expected)
After the program asks for memory size, giving any input will just cause a loop of reading from $F004 (LDA $F004) - i.e. I can't let EhBASIC know when to stop receiving inputs
I want to know an effective method of entering a string of characters, and getting passed "memory size?".
Additionally, if I want to let EhBASIC calculate the memory size automatically, what should I input to $F004?
I'm pretty much a newbie in this area....
I see you use getchar in the code and if I remember correctly that is a blocking call (it will wait until someone presses some key).
In the manual of ehbasic it says:
How to.
The interpreter calls the system routines via RAM based vectors and,
as long as the requirements for each routine are met, these can be changed
on the fly if needs be.
All the routines exit via an RTS.
The routines are ...
Input
This is a non halting scan of the input device. If a character is ready it
should be placed in A and the carry flag set, if there is no character then A,
and the carry flag, should be cleared.
One way to deal with this is to use two threads. One thread that runs the emulation of the 6502 running ehbasic and another thread that polls the keyboard.
Then let the polling thread push any input key strokes into a small buffer from which the ehbasic input routine can use.
Manual: http://www.sunrise-ev.com/photos/6502/EhBASIC-manual.pdf
UPDATE
Reading the question/answer you linked to, I see it is a modified ehbasic.
Your keyboard polling thread should place the keystrokes read in $F004 (and after a while clear F004 again - if I understand the instructions).
UPDATE 2
As a debugging tip: In you first version simply have a string with a fixed input such as 10 print "hello" 20 goto 10 and feed $f004 from there. That way you don't have to worry about any problems with using an actual keyboard.
Not sure how to word the title, but what I'm trying to do is test my micro controller with my Linux PC to ensure data is correct. After hours of searching, I found out that the stty command can change how data is managed through the serial port and it turned out that by default if xon or xoff characters are received from the port, they don't get displayed. At first I thought my computer was too slow that I was losing characters at 57.6Kbps but that wasn't the case.
Back in the day when I was playing with the serial mouse in QuickBasic for DOS, I could use this command to start the serial port:
OPEN "com1:1200,n,7,1,op0" for binary as #1
So what I want to do now is create something simple in C that would allow me to open up the serial port in the rawest mode possible. I want it so that whatever data I give to it is sent to it unmodified. I also want to receive data unmodified. so if the controller decides to send a character the PC would recognize as a special control code, I still want to see the character, not have the PC go funny just because a character matches a control code.
One idea I thought of is to create a fork to the stty program and use nearly every (50+?) parameters added to the program making the requirement of program stack space a bit high.
Another idea I thought of is to do direct I/O with the port address itself (using inb and outb) but I'm not sure if the kernel would run those commands through anything else before the data reaches the port, but I'd rather use that as a last option in case I ever replace my computer and the serial port value changes (or becomes a serial port made through USB to serial converter hardware).
so rather than inb and outb and those variants (like inw), and without executing stty with specifying 50+ parameters in my program, is there a function in C I can use (without requiring a special library not included with a standard linux distribution) to force the serial port device as a raw device so I can do any I/O on it without the kernel modifying or dropping data?
I have barcode scanner, attached to Linux computer via USB. The scanner emulates a keyboard device.
I have to write a program that to read the scanned barcodes and process them. The program runs on background as a service and should read the barcode scanner regardless of the current X focus.
How this can be made in Linux?
Some lower level solution/explanation is preferred.
It sounds like you want to capture the data from a specified device,
In which case the method described in this post should help:
(EDIT: original link dead, Archive link provided)
https://web.archive.org/web/20190101053530/http://www.thelinuxdaily.com/2010/05/grab-raw-keyboard-input-from-event-device-node-devinputevent/
That will listen out for keyboard events stemming from only the specified source.
A word of caution though, as far as I know, that won't stop it from propagating to whatever your current window focus is.
To start with solution, I guess a daemon would perfect choice.
You can write a daemon code, which will open device node (for scanner) and read the data buffer.
Now you have received data in user space, you are free to handle it as per your requirement.
I have this program, we'll call it Host. Host does all kinds of good stuff, but it needs to be able to accept input through the command line while it's running. This means it has to somehow send its other process data and then quit. For example, I need to be able to do this:
./Host --blahblah 3 6 3 5
This should somehow end up calling some function in Host called
handleBlahBlah(int x1, int y1, int x2, int y2){
//do some more sweet stuff
}
Host is a C program, and does not need to support multiple instances.
An example of this is Amarok music player. With Amarok running and playing, you can type "amarok --pause" and it will pause the music.
I need to be able to do this in Linux or Windows. Preferably Linux.
What is the cleanest way to implement this?
If you were on Windows, I'd tell you to use a hidden window to receive the messages, but since you used ./, I assume you want something Unix-based.
In that case, I'd go with a named pipe. Sun has a tutorial about named pipes that might be useful.
The program would probably create the pipe and listen. You could have a separate command-line script which would open the pipe and just echo its command-line arguments to it.
You could modify your program to support the command-line sending instead of using a separate script. You'd do the same basic thing in that case. Your program would look at it's command-line arguments, and if applicable, open the pipe to the "main" instance of the program, and send the arguments through.
If it needs to be cross-platform, you might want to consider making the running instance listen on a TCP port, and have the instance you fire up from the command-line send a message to that port.
I suggest using either a Unix socket or D-Bus. Using a socket might be faster if you're familiar with Unix sockets programming and only want a few operations, whereas D-Bus might make it easier to concentrate on implementing the functionality in a familiar object-oriented way.
Take a look at Beej's Guide to Unix IPC, particularly the chapter on Unix sockets.
What no one has said here is this:
"you can't get there from here".
The command line is only available as it was when your program was invoked.
The example of invoking "fillinthename arguments ..." to communicate with fillinthename once fillinthename is running can only be accomplished by using two instances of the program which communicate with each other.
The other answers suggest ways to achieve the communication.
An amarok like program needs to detect the existence of another instance
of itself in order to know which role it must play, the major role of
persistent message receiver/server, or the minor role of one shot
message sender.
edited to make the word fillinthename actually be displayed.
One technique I have seen is to have your Host program be merely a "shell" for your real program. For example when you launch your application normally (e.g.: ./Host), the program will fork into the "main app" part of your code. When you launch your program in a way that suggests you want to signal the running instance (e.g.: ./Host --send-message restart), the program will fork into the "message sender" part of your code. It's like having two apps in one. Another option that doesn't use fork is to make Host purely a "message sender" app and have your "main app" as a separate executable (e.g.: Host_core) that Host can launch separately.
The "main app" part of your program will need to open up some kind of a communication channel to receive messages, and the "message sender" part will need to connect to that channel and use it to send messages. There are several different options available for sending messages between processes. Some of the more common methods are pipes and sockets. Depending on your OS, you may have additional options available; for instance, QNX has channels and BeOS/Haiku have BMessages. You may also be able to find a library that neatly wraps up this functionality, such as lcm.
So, I may be missing the point here, but by deafult a C program's main function takes two arguments; argc, a count of the number of arguments (at least one), and argv (or arg vector), the argument list. You could just parse through the arguments and call the correct method.
For example:
int main(int argc, *argv[])
{
/*loop through each argument and take action*/
while (--argc > 0)
{
printf(%s%s, *++argv, (argc > 1) ? " " : "");
}
}
would print all of the arguments to screen. I am no C guru, so I hope I haven't made any mistakes.
EDIT: Ok, he was after something else, but it wasn't really clear before the question was edited. Don't have to jump on my rep...