<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: harsh banthiya</title>
    <description>The latest articles on DEV Community by harsh banthiya (@harshbanthiya).</description>
    <link>https://dev.to/harshbanthiya</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F718492%2Fb6e3e5cb-a1fa-40e1-9810-1810f7cfa9c1.jpeg</url>
      <title>DEV Community: harsh banthiya</title>
      <link>https://dev.to/harshbanthiya</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/harshbanthiya"/>
    <language>en</language>
    <item>
      <title>Writing my own minimal shell in C - Part 3(The parsing process leading to an execution tree)</title>
      <dc:creator>harsh banthiya</dc:creator>
      <pubDate>Wed, 06 Oct 2021 17:45:19 +0000</pubDate>
      <link>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-3-the-parsing-process-leading-to-an-execution-tree-42cj</link>
      <guid>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-3-the-parsing-process-leading-to-an-execution-tree-42cj</guid>
      <description>&lt;h2&gt;
  
  
  The Parsing Process
&lt;/h2&gt;

&lt;p&gt;Let's try to put a mental model of how the entire command line string needs to be parsed and what are the various modules we might require along the way. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Scanner -&amp;gt; Parser -&amp;gt; Executer -&amp;gt; Command&lt;/li&gt;
&lt;li&gt;Token_list -&amp;gt; Abstract Syntax Tree -&amp;gt; Convert to Execution Unit -&amp;gt; Execute-Execute&lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  The Tentative Process:
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt;Get the whole string until new line using read_line library. &lt;/li&gt;
&lt;li&gt;Search the string from index 0 until '\0' for ('')&lt;/li&gt;
&lt;li&gt;Divide string in tokens based on whitespace

&lt;ul&gt;
&lt;li&gt;it can be any amount of whitespaces, abcd efgh or abcd     efgh; They should both make two tokens. &lt;/li&gt;
&lt;li&gt;whitespace cannot be included in token characters except when there are double or single quotes. 
** "hello world" is one token hello world
** "" hello world "" is two tokens hello and world; and the empty string before and after hello world will not be tokenized. 
** "'hello world'" -- A single quote inside a double quote will be included in the token, so the result will be one token called 'hello world'; All the above rules apply to single quotes as well. &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt; After dividing the tokens, if there is a token with a $ sign, whatever comes after the $ sign is compared with the list of all the env variables available and replaced with the value of the said variable. 
** Important sub-point - In case of a string in single quote, even if there is a $ sign, it is not replaced with the value of the said env variable. &lt;/li&gt;
&lt;li&gt;Environment variables are received using envp parameter from the main function and stored in a key value structure t_env and put in a linked list. &lt;/li&gt;
&lt;/ol&gt;

&lt;h4&gt;
  
  
  Converting stuff into an Abstract Syntax Tree.
&lt;/h4&gt;

&lt;ol&gt;
&lt;li&gt; A scanner will scan through the string and make a list of tokens based on the rules, we listed above. &lt;/li&gt;
&lt;li&gt; A parser takes that list of tokens verifies the syntax (represents an error if there is a syntax error), and converts it into a tree structure. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Lets try to build the schematics top down:&lt;/p&gt;

&lt;p&gt;----- Command line -----&lt;br&gt;
Job ; command line ; job &lt;br&gt;
(Identify command line (unparsed line) as either a formed job or a combination of jobs and unparsed command_lines)&lt;/p&gt;

&lt;p&gt;----- Job ------&lt;br&gt;
Command | job ; command&lt;br&gt;
(Identify a job as a command or another job in a list)&lt;/p&gt;

&lt;p&gt;---------- Command ----&lt;br&gt;
simple_command redirection list simple_command&lt;br&gt;
(Identify a command as either a simple command or a redirection list )&lt;/p&gt;

&lt;p&gt;---------- Redirection List ---- &lt;br&gt;
redirection redirection_list&lt;/p&gt;

&lt;p&gt;----------- Redirection ------&lt;br&gt;
filename &amp;lt; filename &amp;gt;&amp;gt; filename&lt;/p&gt;

&lt;p&gt;---------- Simple_Command -------&lt;br&gt;
pathname token_list&lt;/p&gt;

&lt;p&gt;----------- Token_List --------&lt;br&gt;
token  token_list&lt;/p&gt;

&lt;p&gt;For example: &lt;br&gt;
cat &amp;gt; a &amp;gt; b &amp;lt; c should end up as:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          command
         /        \
  simple cmd      redirection
  /                      \ 
cat                        &amp;gt;
                          /  \
                       aaaa   &amp;gt;
                             /  \
                          bbbb   &amp;lt;
                                 /
                               cccc 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          (hold)
        /        \
   cat            &amp;gt;
                 /  \
              aaaa   &amp;gt;
                    /  \
                 bbbb   &amp;lt;
                       /
                    cccc 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;          (hold) 
        /        \
   cat            aaaa (type : NODE_REDIRECT_IN)
                    \
                    bbbb (type: NODE_REDIRECT_IN)
                      \
                      cccc (type: NODE_REDIRECT_OUT)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The tree could finally evaluate to Abstract Tree&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;       aaaa (type : NODE_REDIRECT_IN)
      /      \
    cat       bbbb (type: NODE_REDIRECT_IN)
                 \
                 cccc (type: NODE_REDIRECT_OUT)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Let's breakdown the logic of the above command tree:&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;We identify command as one of two structures:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Simple_command and redirection_list structures &lt;/li&gt;
&lt;li&gt;&lt;p&gt;Simple_command structure. &lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;In case of simple command &lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;First we check if it is simple_command&lt;br&gt;
  ** We check the token_list with pathnames &lt;br&gt;
  ** If it just one token we check once but it is a list we check each one. &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;In case of redirection list &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;** We check if it just one redirection or a list. &lt;br&gt;
  ** We attach one case ( &amp;lt;, &amp;gt;, &amp;lt;&amp;lt;, &amp;gt;&amp;gt;) and attach the filename information, create a node and add it to the list.&lt;/p&gt;

</description>
      <category>c</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Writing my own minimal shell in C - Part 2 (The Builtin Functions and general interpretation)</title>
      <dc:creator>harsh banthiya</dc:creator>
      <pubDate>Wed, 06 Oct 2021 15:23:00 +0000</pubDate>
      <link>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-2-the-builtin-functions-and-general-interpretation-4lnb</link>
      <guid>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-2-the-builtin-functions-and-general-interpretation-4lnb</guid>
      <description>&lt;h1&gt;
  
  
  DAY 2 - Understanding the scope of each builtin
&lt;/h1&gt;

&lt;h3&gt;
  
  
  Quick recap of the builtin functions that we need to make
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;echo with the option -n&lt;/li&gt;
&lt;li&gt;cd with only a relative or absolute path&lt;/li&gt;
&lt;li&gt;pwd without any options &lt;/li&gt;
&lt;li&gt;export without any options &lt;/li&gt;
&lt;li&gt;unset without any options &lt;/li&gt;
&lt;li&gt;env without any options and any arguments &lt;/li&gt;
&lt;li&gt;exit without any options&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  cd function
&lt;/h3&gt;

&lt;p&gt;cd can be used with these characters and the sequence matters. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;" . "  - indicates the current folder.&lt;/li&gt;
&lt;li&gt;" .. " - indicates the parent folder. &lt;/li&gt;
&lt;li&gt;" ~ "  - indicates the absolute path to the user.&lt;/li&gt;
&lt;li&gt;" / "  - indicates separation between folders. &lt;/li&gt;
&lt;/ul&gt;

&lt;h4&gt;
  
  
  " ~ " can only be entered as the first argument to cd
&lt;/h4&gt;

&lt;p&gt;cd ~     (this is okay)&lt;br&gt;
cd ./~   (this won't work)&lt;br&gt;
cd dir/~ (this won't work)&lt;/p&gt;

&lt;h4&gt;
  
  
  " / " it can be used as a separator between folders.
&lt;/h4&gt;

&lt;p&gt;cd srcs/ (this is okay)&lt;br&gt;
cd ../   (this is okay)&lt;br&gt;
cd /srcs (this won't work)&lt;/p&gt;

&lt;p&gt;Functions required to write cd function&lt;/p&gt;

&lt;p&gt;getcwd - Get the current path&lt;br&gt;
chrdir - if you put a path in chdir, it moves to that path&lt;/p&gt;

&lt;h3&gt;
  
  
  Handling Quotes
&lt;/h3&gt;

&lt;p&gt;Constraint as discussed over quote handling &lt;/p&gt;

&lt;p&gt;' inhibit all interpretation of the following sequence of characters. &lt;br&gt;
" inhibit all interpretation of the following sequence of characters expect for $&lt;/p&gt;

&lt;h4&gt;
  
  
  Understanding Quotes and how they behave
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;Double quotes must be closed whenever you open one. &lt;/li&gt;
&lt;li&gt;But if you open with a single quote and close with a single quote, any number of double quotation marks can be inserted between them. &lt;/li&gt;
&lt;li&gt;Similarly if you open with double quotes and close with double quotes, any number of single quotes can be inserted between them. &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Valid quote handling for us includes &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; " "&lt;/li&gt;
&lt;li&gt; " ' "&lt;/li&gt;
&lt;li&gt; '  '&lt;/li&gt;
&lt;li&gt; ' " '&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Invalid quote handling for us includes &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; "&lt;/li&gt;
&lt;li&gt; '&lt;/li&gt;
&lt;li&gt; " " '&lt;/li&gt;
&lt;li&gt; ' ' "&lt;/li&gt;
&lt;li&gt; ' " " &lt;/li&gt;
&lt;li&gt; " ' ' &lt;/li&gt;
&lt;li&gt; ' ' '&lt;/li&gt;
&lt;li&gt; " " "&lt;/li&gt;
&lt;/ul&gt;

&lt;h5&gt;
  
  
  Lets look at quotes between executable and variables
&lt;/h5&gt;

&lt;p&gt;Valid quote handling includes: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; echo "abc"&lt;/li&gt;
&lt;li&gt; echo "a"bc&lt;/li&gt;
&lt;li&gt; echo "ab"c&lt;/li&gt;
&lt;li&gt; echo ""abc&lt;/li&gt;
&lt;li&gt; echo abc""&lt;/li&gt;
&lt;li&gt; ech"o" abc&lt;/li&gt;
&lt;li&gt; echo"" abc&lt;/li&gt;
&lt;li&gt; ""echo abc&lt;/li&gt;
&lt;li&gt; "echo" abc&lt;/li&gt;
&lt;li&gt; "echo""" abc&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Invalid quote handling includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; echo" abc&lt;/li&gt;
&lt;li&gt; echo  a"bc&lt;/li&gt;
&lt;li&gt; echo"  a"bc&lt;/li&gt;
&lt;li&gt; echo"  "abc&lt;/li&gt;
&lt;li&gt; ech"o  "abc&lt;/li&gt;
&lt;li&gt; "echo   abc"&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  echo function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Execute echo command with or without args &lt;/li&gt;
&lt;li&gt; Repeat with other arguments&lt;/li&gt;
&lt;li&gt; Restart the shell once done &lt;/li&gt;
&lt;li&gt; If there is conflict, use the conflict flag&lt;/li&gt;
&lt;li&gt; if something doesn't work, use the incomplete flag&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  exit function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Execute with or without args &lt;/li&gt;
&lt;li&gt; exit shell&lt;/li&gt;
&lt;li&gt; same use a conflict flag, incase of a conflict&lt;/li&gt;
&lt;li&gt; if something doesn't work, use a incomplete job flag&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  env function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; display current env variables &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  export function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Export environment variables, create new ones and replace old ones &lt;/li&gt;
&lt;li&gt; export without options prints a list of env variables&lt;/li&gt;
&lt;li&gt; check with env&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  unset function
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; remove environment variables using unset&lt;/li&gt;
&lt;li&gt; check with result in env&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Other Basic information to be aware of
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Simple commands and global
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Shell must be good with simple commands, and commands like /bin/ls and no options&lt;/li&gt;
&lt;li&gt; Test for when empty command line is inserted. &lt;/li&gt;
&lt;li&gt; Test with inserting spaces and tabs at random points &lt;/li&gt;
&lt;li&gt; If something is colliding use a conflict flag&lt;/li&gt;
&lt;li&gt; If something doesn't work, use the incomplete flag. &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Arguments and History
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Must be able to execute simple commands with an absolute path such as /bin/ls with args. Without single and double quotes. &lt;/li&gt;
&lt;li&gt; Repeat with each command and argument&lt;/li&gt;
&lt;li&gt; Use relevant flags for conflict and incomplete.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Return value of a process
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; To mimic the working of $?, execute a simple command with an absolute path or any other command with args but without quotes and double quotes then execute echo $?&lt;/li&gt;
&lt;li&gt; Now try something similar as above but with single quotes and double quotes and check echo $? after that&lt;/li&gt;
&lt;li&gt; Try commands that will fail like bin/ls nonexitantfile and see the value of $?&lt;/li&gt;
&lt;li&gt; Maybe try $? + $? &lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Signals
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; ctrl-c : SIGINT&lt;/li&gt;
&lt;li&gt; ctrl-\ : SIGQUIT&lt;/li&gt;
&lt;li&gt; ctrl-c : Stop execution with an interrupt signal from the keyboard&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ctrl-\ : A stop signal from keyboard, which terminates the process and dumps the core. &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Pressing ctrl-c at an empty prompt should create newline&lt;/li&gt;
&lt;li&gt;If you hit ctrl-\ at the empty prompt, nothing should happen&lt;/li&gt;
&lt;li&gt;Press ctrl-d at an empty prompt to close the shell&lt;/li&gt;
&lt;li&gt;After writing a few things, press ctrl-c to show a new prompt line &lt;/li&gt;
&lt;li&gt;After writing a few things, press ctrl-d, nothing happens&lt;/li&gt;
&lt;li&gt;after writing a few things, press ctrl-\ to turn off the shell&lt;/li&gt;
&lt;li&gt;Block ctrl-c, ctrl-d, ctrl-\ while cat or grep is running. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Incase of conflict, use conflict and incase it doesn't work use the incomplete flag. &lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Single Quotes
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Try an empty parameter&lt;/li&gt;
&lt;li&gt;  Test with env variables, whitespace, pipes and redirects.&lt;/li&gt;
&lt;li&gt;  '%USER' should print $USER&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Relative Path
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;  Repeat with multiple directories with complex relative paths &lt;/li&gt;
&lt;li&gt;  Set $PATH to a multiple directory value(dir1:dir2) and check those directories in left to right order. &lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Next up, Lets try to find the relevant modules to fit all this information and to inbuilt checks at the right spots and the general flow of entire shell.
&lt;/h2&gt;

</description>
      <category>c</category>
      <category>beginners</category>
      <category>programming</category>
    </item>
    <item>
      <title>Always revisit this page when in doubt; The Basics of UNIX philosophy. </title>
      <dc:creator>harsh banthiya</dc:creator>
      <pubDate>Mon, 04 Oct 2021 14:08:19 +0000</pubDate>
      <link>https://dev.to/harshbanthiya/always-revisit-this-page-when-in-doubt-the-basics-of-unix-philosophy-45k9</link>
      <guid>https://dev.to/harshbanthiya/always-revisit-this-page-when-in-doubt-the-basics-of-unix-philosophy-45k9</guid>
      <description>&lt;h1&gt;
  
  
  The basics of Unix Philosophy
&lt;/h1&gt;

&lt;p&gt;It all began with Thompson's efforts on how to design a small but capable operating system with a clean interface. &lt;/p&gt;

&lt;h3&gt;
  
  
  The Unix philosophy is bottom up, not top down.
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt; Doug McIlroy ( the inventor of Unix Pipes ) said: 

&lt;ul&gt;
&lt;li&gt;Make each program do one thing well. To do a new job, build afresh rather than trying to complicate old programs. &lt;/li&gt;
&lt;li&gt;Design and build software to be tried early, don't hesitate to throw away clumsy parts and rebuild them.&lt;/li&gt;
&lt;li&gt;Use tools in preference to unskilled help to lighten programming task. Even if you have to detour to build the tools and expect to throw some of them out after you've finished them. &lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This is the Unix philosophy, write programs that do one thing and they do it well. Write programs to work well together. Write programs to handle text streams, because that is the universal interface. &lt;/p&gt;

&lt;h2&gt;
  
  
  Rules for the Unix tribe, from Rob Pike (Notes on C Programming)
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;You cannot tell where a program is going to spend its time. Bottlenecks occur in surprising places, so don't try to second guess and put in a speed hack until you've proven that's where the bottleneck is. &lt;/li&gt;
&lt;li&gt;Measure. Don't tune for speed until you've measured, and even then don't unless one part of the code overwhelms the rest. &lt;/li&gt;
&lt;li&gt;Fancy algorithms are slow when n is small, n is usually small. Fancy algorithms have big constants. Until you know that n is frequently going to be big, don't get fancy. (even when n get big, use Rule 2 first)&lt;/li&gt;
&lt;li&gt;Fancy algorithms are buggier than simple ones, and they're much harder to implement. Use simple algorithms and simple data structures. &lt;/li&gt;
&lt;li&gt;Data dominates. If you've chosen the right data structures and organized things well, the algorithms are almost always self evident. Data structures and not algorithms are central to programming. &lt;/li&gt;
&lt;li&gt;There is no Rule 6. &lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Similarly there are a few Unix Philosophy implied rules, let's look at them.
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Rule of Modularity: Write simple parts connected by clean interface.
&lt;/h3&gt;

&lt;p&gt;"Controlling complexity is the essence of Computer Programming", Debugging dominated development time and getting a working system out of the door is usually less a result of brilliant design than it is of managing not to trip over your own feet too many times. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Clarity: Clarity is better than cleverness.
&lt;/h3&gt;

&lt;p&gt;Because maintenance is so important and expensive, write programs as if the most important communication they do is not with the computer that executes them but to the humans who will read and maintain the source code in the future (including you). &lt;/p&gt;

&lt;p&gt;Thats doesn't just mean comments, it also embraces choosing your algorithms and implementations for future maintainability. Buying a small increase in performance with a large increase in complexity and obscurity of your technique is a bad trade. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Composition: Design programs to be connected with other programs.
&lt;/h3&gt;

&lt;p&gt;Unix tradition strongly encourages writing programs that read and write simple, textual, stream-oriented, device independent formats. Under classic Unix, as many programs as possible are written as simple filters, which take a simple text stream on input and process it into another simple text stream on output. &lt;/p&gt;

&lt;p&gt;To make programs composable, make them independent. A program on one end of a text stream should care as little as possible about the program on the other end. It should be easy to replace one end with a completely different implementation without disturbing the other. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Separation: Separate policy from mechanism; separate interfaces from engines.
&lt;/h3&gt;

&lt;p&gt;Policies are ways to choose which activities to perform, Mechanisms are implementations that enforce policies. Policy and Mechanisms mutate on different timescales, with policy changing much faster than mechanism. &lt;br&gt;
Thus, hardwiring policy and mechanism together has two bad effects; it makes policy rigid and harder to change in response to user requirements, and it means that trying to change policy has a strong tendency to destabilize the mechanisms. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule for Simplicity: Design for simplicity, add complexity only where you must.
&lt;/h3&gt;

&lt;p&gt;No need for technical machismo. Programmers are bright people who are (often justly) proud of their ability to handle complexity and juggle abstractions. Often they compete with their peers to see who can build the most intricate and beautiful complexities. Their ability to design outstrips their ability to implement and debug and the result is an expensive failure. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Parsimony: Write a big problem only when it is clear by demonstration that nothing else will do.
&lt;/h3&gt;

&lt;p&gt;'Big' here has the sense of both large in volume of code and of internal complexity. Allowing programs to get large hurts maintainability. Because people are reluctant to throw away the visible product of lots of work, large programs invite over-investment in approaches that are failed or suboptimal.&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Transparency: Design for visibility to make inspection and debugging easier.
&lt;/h3&gt;

&lt;p&gt;Debugging occupied three quarters or more of our development time. A system is transparent when you can look at it and immediately understand what it is doing and how. It is discoverable when it has facilities for monitoring and display of internal state so that your program not only functions well but can be seen to function well. &lt;/p&gt;

&lt;p&gt;Designing these qualities have implications from the very beginning. At minimum, it implies that it must use simple interfaces, that can be easily manipulated by other programs - in particular, test and monitoring harnesses and debugging scripts. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Robustness: Robustness is the child of transparency and simplicity.
&lt;/h3&gt;

&lt;p&gt;Software is robust when it performs well under unexpected conditions which stress the designer's assumptions, as well as normal conditions. &lt;/p&gt;

&lt;p&gt;One very important tactic for being robust under odd inputs is to avoid having special cases in your code. Here is another way to make simple and robust software. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Representation: Fold knowledge into data, so program logic can be stupid and robust.
&lt;/h3&gt;

&lt;p&gt;Even the simplest procedural logic is hard for humans to verify. Data is more tractable than program logic. It follows that where you see a choice between complexity in data structures and complexity in code, choose the former. In evolving a design, you should actively seek ways to shift complexity from code to data. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Least Surprise: In interface design, always do the least surprising thing.
&lt;/h3&gt;

&lt;p&gt;The easiest programs to use are those that demand the least new learning from the user, or to put in another way, the easiest programs to use are those that most effectively connect the user's pre-existing knowledge. Well designed programs treat the users attention and concentration as a precious and limited resource, only to be claimed when necessary. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Repair: Repair what you can - but when you must fail, fail noisily and as soon as possible.
&lt;/h3&gt;

&lt;p&gt;Yes it is best when software can cope with unexpected conditions by adapting to them, but the worst kind of bugs are those in which repair doesn't succeed and the problem quietly causes corruption that doesn't show up until later. &lt;/p&gt;

&lt;p&gt;"Be liberal in what you accept, but conservative in what you send." Well-Designed programs co-operate with other programs by making as much sense as they can from ill-formed inputs; they either fail noisily or pass strictly clean and correct data to the next program in the chain. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Economy: Programmer time is expensive; conserve it in preference to machine time.
&lt;/h3&gt;

&lt;p&gt;In older days, machines were slower and much expensive; Now however we can make use of cheap machine cycles now. Code in higher level languages, ease programmer's burden by letting languages do their own memory management. &lt;/p&gt;

&lt;p&gt;The obvious way to conserve programmer time is to teach machines how to do more of the low level work of programming. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Generation: Avoid hand-hacking; write programs to write programs when you can.
&lt;/h3&gt;

&lt;p&gt;Human beings are notoriously bad at sweating the details. Any kind of hand hacking is rich source of delays and errors. Generated code (at every level) is almost always cheaper and more reliable than hand-hacked. That's why we have compilers and interpreters. It pays to use code generators when they can raise the level of abstractions - that is when the specification language for the generator is simpler than the generated code. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Optimization: Prototype before polishing. Get it working before you optimize it.
&lt;/h3&gt;

&lt;p&gt;"90% of functionality delivered now is better than 100% of it delivered never"; premature optimization before the bottlenecks are known is only error to have ruined more designs than feature creep. Often local premature optimization, hinders global optimization. "Make it run, then Make it run right, then make it fast."&lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Diversity: Distrust all claims for "one true way"
&lt;/h3&gt;

&lt;p&gt;Even the best software tools tend to be limited by the imaginations of their designers. Nobody is smart enough to optimize for everything, nor to anticipate all the uses to which their software might be put. Embrace multiple languages, open extensible systems and customization hooks everywhere. &lt;/p&gt;

&lt;h3&gt;
  
  
  Rule of Extensibility: Design for future, because it will be here sooner than you think.
&lt;/h3&gt;

&lt;p&gt;If it is unwise to trust other people's claims for "one true way", it is even more foolish to believe them about your own designs. Never assume you have the final answer. Therefore, leave room for your data formats and code to grow, otherwise you are locked with unwise early choices because you cannot change them while maintaining backward compatibility. &lt;/p&gt;

&lt;p&gt;When you design protocols or file formats, make them sufficiently self describing to be extensible. Always, always either include a version number, or compose the format from self contained, self describing clauses in such a way that new clauses can be readily added and old ones dropped without confusing format reading code. &lt;/p&gt;

&lt;p&gt;When you design code, organize it so future developers will be able to plug new functions into the architecture without having to scrap and rebuild the architecture. Put in the "if you ever need to ...  " comments.&lt;/p&gt;

&lt;p&gt;When you design for the future, the sanity that you save may be your own. &lt;/p&gt;

</description>
      <category>opensource</category>
      <category>c</category>
      <category>beginners</category>
      <category>codenewbie</category>
    </item>
    <item>
      <title>Writing my own minimal shell in C - Part 1 (The constraints)</title>
      <dc:creator>harsh banthiya</dc:creator>
      <pubDate>Sun, 03 Oct 2021 21:38:52 +0000</pubDate>
      <link>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-1-the-constraints-20cg</link>
      <guid>https://dev.to/harshbanthiya/writing-my-own-minimal-shell-in-c-part-1-the-constraints-20cg</guid>
      <description>&lt;h1&gt;
  
  
  Day 1 - Understanding the Problem.
&lt;/h1&gt;

&lt;p&gt;This is my attempt to replicate the behavior of BASH or (Bourne again shell) command line interpreter for a school project. Before we get into how to get into the solution and the general approach of making the shell. Let's first look at all the constraints and what is expected from this minimal shell. &lt;/p&gt;

&lt;h2&gt;
  
  
  First and foremost, standard library functions I am allowed to use.
&lt;/h2&gt;

&lt;p&gt;Below is the list of the external functions / standard library functions that I am allowed to use, if I need any another function I must code it myself. Please see the man pages of these functions if you do not recognize them. &lt;/p&gt;

&lt;p&gt;readline, rl_clear_history, rl_on_new_line, rl_replace_line, rl_redisplay, add_history, printf, malloc, free, write, access, open, read, close, fork, wait, waitpid, wait3, wait4, signal, sigaction, kill, exit, getcwd, chdir, stat, lstat, fstat, unlink, execve, dup, dup2, pipe, opendir, readdir, closedir, strerror, perror, isatty, ttyname, ttyslot, ioctl, getenv, tcsetattr, tcgetattr, tgetflag, tgetnum, tgetstr, tgoto, tputs&lt;/p&gt;

&lt;h2&gt;
  
  
  Expectations from the shell, what must this minimal shell do
&lt;/h2&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;It must implement the builtin shell functions &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; echo with the option -n&lt;/li&gt;
&lt;li&gt; cd with only a relative or absolute path&lt;/li&gt;
&lt;li&gt; pwd with no options &lt;/li&gt;
&lt;li&gt; export with no options &lt;/li&gt;
&lt;li&gt; unset with no options &lt;/li&gt;
&lt;li&gt; env with no options or arguments &lt;/li&gt;
&lt;li&gt; exit with no options &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Redirections &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; &amp;lt; should redirect input&lt;/li&gt;
&lt;li&gt; &amp;gt; should redirect output &lt;/li&gt;
&lt;li&gt; &amp;lt;&amp;lt; read input from the current source until a line containing only the delimiter is even. &lt;/li&gt;
&lt;li&gt; &amp;gt;&amp;gt; should redirect output in append mode.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Pipes &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; | The output of each command in the pipeline is connected via a pipe to the input of the next command&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Environment Variables ($ followed by characters ) should expand to their values.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;$? should expand to the exit status of the most recently executed foreground pipeline&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;For some simplification, the shell must not interpret unclosed quotes or unspecified special characters like '\' or ';' etc&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;The shell must show a prompt waiting for next command, have a working history and must only use one global variable.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;ctrl-C ctrl-D ctrl-\ should work like bash. When interactive:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt; ctrl-C print a new prompt on a newline&lt;/li&gt;
&lt;li&gt; ctrl-D exit the shell.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Lets begin researching the problems and the areas of Operating System I am less familiar with, in the next part of this series I will break down the general overview of the design and I will try to make it super modular.
&lt;/h2&gt;

</description>
      <category>c</category>
      <category>programming</category>
      <category>beginners</category>
    </item>
  </channel>
</rss>
