{"id":7350,"date":"2026-01-17T00:01:58","date_gmt":"2026-01-17T08:01:58","guid":{"rendered":"https:\/\/c-for-dummies.com\/blog\/?p=7350"},"modified":"2026-01-24T11:32:35","modified_gmt":"2026-01-24T19:32:35","slug":"reading-raw-input","status":"publish","type":"post","link":"https:\/\/c-for-dummies.com\/blog\/?p=7350","title":{"rendered":"Reading Raw Input"},"content":{"rendered":"<p>Switching between <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7339\">cooked and raw modes<\/a> requires access to the terminal&#8217;s configuration data. In Linux, these settings are manipulated at the command prompt by using the <em>stty<\/em> ccommand. In a C program, you use various functions available in the standard library and defined in the <code>termios.h<\/code> header file.<br \/>\n<!--more--><br \/>\nI&#8217;ve written about modifying the terminal configuration <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=4001\">before<\/a>, specifically to suppress a terminal&#8217;s character echo. The process involves obtaining the current terminal configuration, duplicating it, then modifying the duplicate to reflect new settings. The original terminal configuration can then be restored.<\/p>\n<p>The <em>tcgetattr()<\/em> function obtains the current terminal configuration. Here&#8217;s the <em>man<\/em> page format:<\/p>\n<p><code>int tcgetattr(int fd, struct termios *termios_p);<\/code><\/p>\n<p>Argument <code>fd<\/code> is a file descriptor. This value isn&#8217;t the same as <em>stdin<\/em>. Instead, use <code>fileno(stdin)<\/code> or the <code>STDIN_FILENO<\/code> defined constant (from <code>unistd.h<\/code>).<\/p>\n<p>The <code>termios_p<\/code> argument is the address of a <em>termios<\/em> structure. Its members hold various terminal attributes, including local echo and canonical (raw\/cooked) modes.<\/p>\n<p>After manipulating members of the <em>termios<\/em> structure, use the <em>tcsetattr()<\/em> function to apply modifications to the terminal&#8217;s behavior. Here is this function&#8217;s <em>man<\/em> page format:<\/p>\n<p><code>int tcsetattr(int fd, int optional_actions, const struct termios *termios_p);<\/code><\/p>\n<p>As with <em>tcgetattr()<\/em>, the arguments start with the file descriptor, <code>fd<\/code>, which is the same for the <em>tcgetattr(<\/em>) function when modifying the current terminal. The <code>optional_actions<\/code> argument is a defined constant that determines when the changes take effect. Most often <code>TCSANOW<\/code> is used to have the changes take place immediately. The final argument is the address of the <em>termios<\/em> structure containing any terminal modifications.<\/p>\n<p>The <em>man<\/em> page lists the members of the <em>termios<\/em> structure and the host of options that you can mess with. For switching to raw input mode, the <code>ICANON<\/code> constant is manipulated in the <code>c_clfag<\/code> member of the <em>termios<\/em> structure, which is demonstrated in the following code:<\/p>\n<h3><a href=\"https:\/\/github.com\/dangookin\/C-For-Dummies-Blog\/blob\/master\/2026_01_17-Lesson.c\" target=\"_blank\" rel=\"noopener\">2026_01_17-Lesson.c<\/a><\/h3>\n<pre class=\"screen\">#include &lt;stdio.h&gt;\r\n#include &lt;termios.h&gt;\r\n\r\n<span class=\"comments\">\/* read input and write output *\/<\/span>\r\nvoid in_out(void)\r\n{\r\n    int x;\r\n    char buffer[BUFSIZ];\r\n\r\n    printf(\"Type some text: \");\r\n    <span class=\"comments\">\/* read input *\/<\/span>\r\n    fgets(buffer,BUFSIZ,stdin);\r\n\r\n    <span class=\"comments\">\/* send output *\/<\/span>\r\n    printf(\"Buffer: \");\r\n    for( x=0; buffer[x]; x++ )\r\n        printf(\"%02X \",buffer[x]);\r\n    putchar('\\n');\r\n}\r\n\r\nint main()\r\n{\r\n    struct termios original,raw;\r\n\r\n    <span class=\"comments\">\/* first read stdin cooked *\/<\/span>\r\n    puts(\"Cooked mode on\");\r\n    in_out();\r\n\r\n    <span class=\"comments\">\/* disable cannonical terminal mode *\/<\/span>\r\n    tcgetattr(fileno(stdin),&amp;original);\r\n    raw = original;\r\n    raw.c_lflag = raw.c_lflag ^ ICANON;\r\n    tcsetattr(fileno(stdin),TCSANOW,&amp;raw);\r\n\r\n    <span class=\"comments\">\/* read stdin raw *\/<\/span>\r\n    puts(\"Raw mode on\");\r\n    in_out();\r\n\r\n    <span class=\"comments\">\/* restore and clean-up *\/<\/span>\r\n    tcsetattr(fileno(stdin),TCSANOW,&amp;original);\r\n    return 0;\r\n}<\/pre>\n<p>The <em>main()<\/em> function calls function <em>in_out()<\/em> to test input and output in cooked mode. In the <em>in_out()<\/em> function, text is read into a buffer and then output as a series of hexadecimal values.<\/p>\n<p>After cooked output is examined, the <em>main()<\/em> function obtains the current terminal&#8217;s configuration:<\/p>\n<p><code>tcgetattr(fileno(stdin),&amp;original);<\/code><\/p>\n<p>A duplicate is made of the original <em>termios<\/em> structure and saved in structure <code>raw<\/code>. Then the <code>c_clflag<\/code> is set to disable canonical mode:<\/p>\n<p><code>raw.c_lflag = raw.c_lflag ^ ICANON;<\/code><\/p>\n<p>The new terminal attributes are applied with <code>tcsetattr(fileno(stdin),TCSANOW,&amp;raw)<\/code>, and the <em>in_out()<\/em> function called again to examine input.<\/p>\n<p>At Line 40, the <em>tcsetattr()<\/em> function restores the original terminal configuration, <code>original<\/code>. This configuration may be restored automatically when the program quits. If not, use the <em>reset<\/em> command in the terminal window to bring things back to normal.<\/p>\n<p>Here&#8217;s a sample run:<\/p>\n<pre>Cooked mode on\r\nType some text: he\r\nBuffer: 68 65 0A\r\nRaw mode on\r\nType some text: hello^?^?^?\r\nBuffer: 68 65 6C 6C 6F 7F 7F 7F 0A<\/pre>\n<p>In the first run, I typed <strong>hello<\/strong> and then backspaced three times. The backspace (DEL) characters aren&#8217;t retained in the input. But when raw input is activated, you see the DEL characters (<code>^?<\/code>) in the output as well as how they were saved in the buffer (<code>7F<\/code>).<\/p>\n<p>Entering raw mode may seem silly, but circumstances exist where it&#8217;s necessary to fetch uncooked input and have your program process it directly. I&#8217;ll provide an example in a future Lesson.<\/p>\n<p>For <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7357\">next week&#8217;s Lesson<\/a>, I cover direct terminal input, which can be confused with raw mode due to some quirky output.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In raw mode, the terminal report all characters input &mdash; no cooking allowed! <a href=\"https:\/\/c-for-dummies.com\/blog\/?p=7350\">Continue reading <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-7350","post","type-post","status-publish","format-standard","hentry","category-main"],"_links":{"self":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7350","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=7350"}],"version-history":[{"count":4,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7350\/revisions"}],"predecessor-version":[{"id":7372,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/7350\/revisions\/7372"}],"wp:attachment":[{"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=7350"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=7350"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/c-for-dummies.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=7350"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}