Saturday, October 5, 2013

What does the cowsay?

Rather than wine-ing about how long it's been since my last post, I thought I would move directly into pop culture today. Many of you may have heard Ylvis's song "The Fox," where a single question is posed and repeated over and over again: "What does the fox say?" This is, of course, a silly question. The sound of the fox has been recorded before, and sounds nothing like Ylvis's interpretation of what they might sound like. That being said, today I would like to introduce an old linux command: cowsay. It's function is somewhat self-explanatory: it creates an ASCII cow that says whatever you want it to say.

What is the purpose in this command? There is none, and that's okay. If there were a purpose to every linux command, video games would never have been invented. Because the ASCII image is somewhat dependent on the text used, I will be posting the outputs directly from my terminal. Here is an example output:

$cowsay "Hey, at least I'm not a pig"



If you are anything like me, you might be thinking, "Okay. This command is cool, but what else does it do?" Short answer: a bunch more. 

  • -b enacts borg mode
  • -t yields a tired cow
  • -d provides a dead cow
  • -s surprises the cow (sometimes referred to as a "stoned cow")
  • -g makes the cow greedy
  • -p causes paranoia
  • -w causes the cow to be wide awake
  • -y gives the cow youthful, kiddy eyes
  • -l lists all the other cow files you can pull from (likely out of /usr/share/cows)
  • -f chooses an alternative cowfile to use from the "l" flag's list

What types of cows are available? Quite a few. A full list can be found at the end of this post. Before that, though, I would like to take a minute to go over a new "cow" I have created: the fox. Just how did I do this? Well, I created an ASCII fox image that looked something like this:



I then navigated to /usr/share/cows and created the file "fox.cow". Now, in order to format the file appropriately and allow the fox to have changeable eyes, the image in the file ended up resembling a headless chicken, rather than a fox. After using the command, though, it ended up working pretty well. Here is the text:

##
## A fox, Leios
##
$eyes = "oo" unless ($eyes);
$the_cow = <<EOC;
 $thoughts              /\\
  $thoughts             )~)
    /\\/\\       ( (
   ( $eyes )_-------_)
    \\__/         )
     \\/ /|/---\\|\\
      .. ..  ..  ..
EOC


If you simply copy and paste that into a new "fox.cow" file, located in your $COWPATH (likely /usr/share/cow), you should be able to see the following:

$cowsay -f fox "I really sound like a dog"



And there you have it folks! What does the fox say? Anything your little penguin heart desires. The following is a list of all the "cows" available for you after installing from the Arch repositories:

[WARNING] Most of these images were made by linux users. [/WARNING]

  • bong
  • bud-frogs 
  • bunny 
  • cheese 
  • cower 
  • daemon 
  • default 
  • dragon
  • dragon-and-cow 
  • elephant 
  • elephant-in-snake
  • eyes 
  • flaming-sheep 
  • ghostbusters 
  • head-in 
  • hellokitty 
  • kiss 
  • kitty 
  • koala 
  • kosh 
  • luke-koala 
  • meow 
  • milk
  • moofasa 
  • moose 
  • mutilated 
  • ren 
  • satanic 
  • sheep 
  • skeleton 
  • small 
  • sodomized
  • stegosaurus 
  • stimpy 
  • supermilker 
  • surgery 
  • telebears 
  • three-eyes 
  • turkey turtle
  • tux 
  • udder 
  • vader
  • vader-koala 
  • www

                                                                                      If there are any physicists still reading:


                                                                                      Monday, May 20, 2013

                                                                                      Winning With WINE


                                                                                      Gaming is becoming more and more common in the linux world thanks to the efforts of modern gaming companies like Valve. Because of this, more and more games have native linux clients available. For those games, Windows emulation is clearly not the best option, but for other games that have not yet been ported to linux, such as Guild Wars 2, windows emulation might be a good option. In those cases, search for the games or related software at WineHQ's application database. Their organization scheme system has five levels: Platinum, Gold, Silver, Bronze, and Garbage. Each one designates the level of usability of the software. If you check out specific pages, you can see why certain software has been given certain ranks and figure out how to make your Wine experience worthwhile. For some users, this is as far as they need to go. If a program is well-supported, they buy it. If not, the don't. Still, there is a lot more to Wine than meets the eye.

                                                                                      First of all, though I have been calling Wine a "Windows emulator," the acronym "WINE" stands for "Wine Is Not an Emulator." In fact, it is not. It is closer to a compatability layer. There are also many tricks you can use to ensure your game is running as effectively as possible. Remember that the generic Wine build is not the only one available, and as a user of open-source software, it is your right and privilege to modify or patch the software to fit your system.

                                                                                      The easiest way to modify your Wine build is to use the winecfg tool. After running the command, you should see the following GUI:


                                                                                      From here, you can change basic settings for your programs. Typically, the important changes to help your program along can be found in the AppDB.

                                                                                      The next important tool is regedit. After using this command, you will find the following filesystem appear:


                                                                                      The most common edit here is to add specifications such as video memory size. This can be done by navigating to the HKEY_CURRENT_USER/Software/Wine/Direcd3D folder, and adding in the string "VideoMemorySize" with a value appropriate for your graphics card. This can be done by right clicking and adding the folder Direct3D, and then adding and editing the string in the same fashion.

                                                                                      In addition to these two editors, you could also try Q4Wine for Qt systems, but the documentation is much more difficult to find.

                                                                                      If you wish to have different Wine builds for each different program, along with an easy install, you could install PlayOnLinux. Most Wine users will use PlayOnLinux to manage their Wine builds.

                                                                                      There is, of course, the option of compiling your own version of Wine for your system and applications using Wine-git using a tutorial found here. To do this, you must first use the mkdir command to create a wine-git directory, and then download the latest wine version to it, like so:


                                                                                      git clone git://source.winehq.org/git/wine.git ~/wine-git
                                                                                      cd ~/wine-git


                                                                                      Once done, you should be able to run


                                                                                      $ git config remote.origin.url


                                                                                      and receive the following result:


                                                                                      git://source.winehq.org/git/wine.git


                                                                                      In addition, if you plan on ever submitting a patch to WineHQ, you might want to set your name and e-mail address like so:


                                                                                      git config --global user.name "Your Name"
                                                                                      git config --global user.email "me@example.com"


                                                                                      You might want to also run:


                                                                                      git config --global color.ui auto


                                                                                      for some colored commands and:


                                                                                      git config --global format.suffix .txt


                                                                                      to make sure all of the patches you receive are converted into .txt files.

                                                                                      Once all that is done, we can begin working with Wine-git--however, that is a lot for a single blog post. I will save off on this until tomorrow and revise the schedule accordingly.

                                                                                      As always, thanks for reading.
                                                                                      -Leios

                                                                                      Sunday, May 19, 2013

                                                                                      Week 3 of KeroCG's Summer of Code!

                                                                                      Here is the posting schedule for this upcoming week:

                                                                                      Monday: Winning with WINE
                                                                                      Tuesday: Winning With WINE II
                                                                                      Wednesday: Qt's return
                                                                                      Thursday: GTK+ more
                                                                                      Friday: A look into game development
                                                                                      Saturday: C-world
                                                                                      Sunday: A look at OpenGL

                                                                                      Feel free to let me know if there is anything in particular you would like for me to cover.

                                                                                      Thanks again for reading!
                                                                                      -Leios

                                                                                      A Window into Windows: Linux Options

                                                                                      If you have used linux for any length in time, you might have noticed one of it's greatest fallbacks: compatability with Windows. The fact is that developers develop for Windows, and the linux crowd has to bend over backwards to use the software. In my case, I see this struggle every day with games of all kinds. I have also heard of artists complaining about limited access to adequate art programs or doctors using Windows-only technology. Though many companies are finally starting to back linux, it will still be at least a decade before any big paradigm shifts occur in the OS world. We will be stuck with Windows fore a while, that's for sure.

                                                                                      What do we do about it? Well, we find work arounds for the programs we need. Generally, there are four options:

                                                                                      1. Open-Source equivalents

                                                                                      2. Compatability Layers

                                                                                      3. Virtualization Environments

                                                                                      4. Dual-Booting

                                                                                      I will cover each in brief detail:


                                                                                      Using Open Source Equivalents

                                                                                      In many cases, linux communities from all around have created their own version of a necessary programs. For a simple 2-D art program, for example, there is GIMP, which also has it's own photoshop varient, and for 3-D modeling, there is Blender. Both of these projects have very well-done examples that prove they are equivalent to their closed-source brethren in almost every way. I am not an artist, but after using them for a bit, I feel I have become used to them and would love to do some more difficult projects with them in the future. That being said, open source equivalents are often different than their closed cousins and may take a little more time to get used to. 

                                                                                      These are, of course, just two examples of many. Your best bet to finding the open source equivalent to the software you want is to do a quick google search about it. Still, in some cases, like if you are an artist or a gamer, the open source equivalents are just not what you want. If that's the case, you should look into more complicated solutions.


                                                                                      Using Windows Compatability Layers

                                                                                      Most distributions nowadays come with a software package known as WINE somewhere in their software center. This is essentially a Windows emulation tool that allows linux-users to use many Windows programs while still on their linux desktop. In most cases, the application works fairly well and the software is usable, but not always as usable as in Windows natively. That being said, WINE is completely patchable and definitely worth a shot with whatever software you are looking for. 


                                                                                      Virtualization

                                                                                      In some cases, neither the open source varients or WINE are good enough. In these cases, you can use a virtualization environment, such as Virtualbox of VMWare, to run Windows inside of linux. These programs work by allowing Windows to leech off your RAM and act as if it were running outside of linux. If you have enough RAM, this might be a good option for you.

                                                                                      Alternatively, you could set up a Windows PC as a remote desktop server and access it with remote desktop applications like rdesktop or remmina. This solution is a little messier than standard virtualization, as it requires another system to be already running Windows somewhere over the rainbow, but it is certainly an available option.


                                                                                      Dual Booting

                                                                                      If all other solutions have failed you, you can always reboot your system into Windows when necessary to use the appropraite software. This is a pretty simple option and is used frequently for linux gamers who need as much performance as they get.


                                                                                      Even though developers do not often develop for linux, most of the time necessary software is available for us to use in some fashion. If you are currently using Windows and thinking about switching to linux, know that your favorite programs are mostly usable and that you do not have to be rid of your Windows installation completely. Ease yourself into the OS and get used to how it works first. If you like it, keep it. If you don't like it, stick to Windows. Whatever the case, do what makes sense for you.

                                                                                      Thanks for reading,
                                                                                      -Leios

                                                                                      Saturday, May 18, 2013

                                                                                      Linux Viruses: Fact or Fiction?

                                                                                      Imagine you are a malicious virus writer. Your goal is to spread some toxic code to as many people as quickly as possible without getting caught. You have three operating systems to choose from: 

                                                                                      -Linux, an OS that only about 1% of the population uses. It is riddled with different platforms along with a close-knit community to filter any malicious code that enters their user-repositories and also has additional security levels to break through. 

                                                                                      -Mac OSX, the second most popular OS that shares many of linux's security features but without the community or varied platforms. 

                                                                                      -Windows, the most popular desktop OS by a significant margin with completely closed-source code and few security features.

                                                                                      Which OS would you choose? Windows, obviously. What is your second choice? Mac. At least with Mac you know what you are dealing with. Writing viruses for Linux, though, is kind of like going to an archery range blindfolded while trying to hit a quarter-sized target 25 yards away. Sure, if you shoot enough arrows, you might hit your target, but you've got to have a lot of luck and a lot of spare time. 

                                                                                      Let's imagine, though, that you did have the time and luck. How would you go about infecting a linux computer? Well, you would first choose the distribution you would like to infect. That's not exactly the easiest thing to do, as there are hundreds of distributions to choose from. Generally speaking, though, these can be broken down into three different file formats: .deb, .rpm, and .tar.gz. If you want to infect Fedora or a BSD, choose .rpm. If you want to infect Arch, choose .tar.gz. If you want to infect Ubuntu, choose .deb.

                                                                                      Once that is decided, you then have to work your way through user permissions. Generally speaking, linux distributions have users with fewer rights than root. That means if you do successfully infect a linux computer, you can only go as far as the user allows. You would actually have to prompt the user to give you his root password to infect the entire computer. Otherwise, you would just have to settle with a measely home directory. That means you've got to be pretty sneaky to trick a user into installing your virus with the appropriate permissions.

                                                                                      The linux desktop environment also changes much faster than Windows or Mac, with popular distributions offering new releases every six months and some distributions offering immediate, bleeding-edge software packages. This means that your virus would have to stay current or else attack a package that does not update regularly. 

                                                                                      In addition, almost all distributions have a central repository to download software from that has definitely been checked for viruses and malware, which means that most linux users, unlike Windows users, do not download software online. You could, potentially, sneak your virus in to a non-official repository (such as the AUR), but even then packages are checked by the community members who use them. 

                                                                                      When it's all said and done, if you do try to write a virus for linux, you have a lot to go through for very little reward. That being said, there are a number of viruses (some of which are "proof of concept" viruses) that can infect your computer. On top of that, your linux computer can carry viruses to be sent through e-mail to Windows (or Mac) devices. If you intend to set up any sort of mail client, a virus-scanner is a must!

                                                                                      Bottom line: if you use linux do not think you are impervious to attacks. That is simply not the case. Any online information, such as your banking account, can be subject to attack and some malicious code can be snuck into any of your downloaded content. Be careful when downloading new content from online or non-official sources. Be sure the packages you use have high approval ratings. Above all, though, use common sense. If you ever seem to be alone on the internet or are the only user downloading a particular item, close your broswer or crash your code! Just because your machine is unlikely to get a virus does not mean you should put it at risk. 

                                                                                      It is also expected that the number of linux viruses will increase in the upcoming years due to the increasing popularity of the OS as a gaming platform and thus as a viable desktop operating system. If you are using a popularized distribution, like Ubuntu, you might be one of the first at risk. Even if you are not using a popular distribution, it is not good practice to go without a virus scanner on your computer.

                                                                                      A few weeks ago, a virus known as darkleech began attacking Apache servers everywhere, followed quickly by Cdorked. More technical information on Cdorked can be found here. These are both backdoors that allow hackers to upload malicious code directly to the infected server or drive traffic to malicious websites. We should be careful moving foward with Apache in the future because of this. I will probably return to the idea of viruses in more detail later (I'm becoming interested). 

                                                                                      Agian, though your own system might not be in as much risk as a Windows device, you might want to look into a virus scanner or two. I know from personal experience that the CLI for avast is decent for detecting Windows-only viruses. For linux viruses, sophos along with rkhunter and Chkrootkit should find them.

                                                                                      As always, thanks for reading and be safe out there.
                                                                                      -Leios.

                                                                                      Friday, May 17, 2013

                                                                                      Linux Hardware: A World of Possibilities?

                                                                                      Throughout the past year or so, I have been a part of a group that hosts several "linux nights," which are opportunities for us to get together to install linux or fix anything wrong with our systems. Generally speaking, I find them enjoyable and would encourage anyone interested in computing to host one or two to generate interested in linux and computing in general. At the last meeting, however, we discussed why linux cannot seem to compete as a desktop platform, when it is clearly successful everywhere else. In the end, we agreed that one reason is because linux does not come pre-installed on any real market computer. Users must go out of their way to use the OS, which means they must take time out of their day not only to learn an entirely new operating system, but they must also to proceed through a typically painful installation process. On top of that, rather than lending a helping hand to new users, a significant portion of the linux community will scoff and ask, "did you read the manual?" This is not cool.

                                                                                      That being said, linux is becoming much more popularized, especially in the gaming world, with Valve supporting it 100%. It is even competing with mac as a secondary gaming platform. Objectively speaking, though, Windows still beats the snot out of linux in the desktop market. When people buy computers, it generally comes pre-installed with Wndows unless it is a mac product. Because of that, most programs run on Windows, not mac or linux, and because of that, most consumers want to buy Windows products. It is a somewhat vicious marketing cycle for any consumer wishing to buy another OS. On top of that, most of the regular linux users are used to the installation processes of their primary distributions and don't mind writing over their Windows device after purchase. 

                                                                                      Generally speaking, if you wish to buy a natively linux computer, you only have a few vendors to choose from, none of which you are likely to find at your local Best Buy. Here are my top three choices:

                                                                                      Dell- On several devices, Dell offers Ubuntu as a pre-installed OS, however after this incident, they are probably wary to popularize it. Still, there are some decent deals, like this Alienware, for instance. Generally, though, Dell prefers to support Windows.

                                                                                      System76- This is my personal favorite Linux vendor. They offer competatively priced, ubuntu-only laptops, desktops, and servers, including some gaming powerhouses, like their Leopard Extreme desktop or Bonobo Extreme laptop. They also offer fantastic economy systems for the linuxer on a budget. On top of that, their Windows key has the Ubuntu logo on it.

                                                                                      ZaReason- Truth be told, this vendor costs a little more, but has many more options to choose from. They also support more than just Ubuntu and will install any distribution you wish. Beyond that, they allow you to use have a tux or Ubuntu logo on your Windows key, which is pretty cool in my book.

                                                                                      There are also some fringe vendors that cost too much or are too outdated to be mentioned here. You might be asking yourself, "How do linux computers cost more than Windows when the OS is free?" Well, that's because Windows comes with a bunch of bloatware to mitigate it's cost. That's the whole of it--the market economy, at its finest.

                                                                                      Though I would encourage using any of the above vendors, I understand that sometimes you might not have time for a new computer to come in or that it really is cheaper to buy a Windows machine and install linux on it yourself (be wary of Windows 8, though). That being said, here are a few tips to buying a PC for linux:

                                                                                      1. Be wary of AMD- Generally speaking, Nvidia and Intel graphics cards are much better adapted for linux machines. Though this is not as true for newer graphics cards, partially thanks to Valve's influence, it is still something to look out for.

                                                                                      2. Google the machine beforehand- Before purchasing a machine for linux, find out the model number and look it up along with the word "linux" in google. Also, make sure you have as much information about the system as possible before buying. This might be a silly rule, but it could definitely save you some trouble down the road.

                                                                                      3. Don't necessarily look for the latest and greatest- When shopping for a new PC, remember that it might take time for the linux community to work in new hardware advancements. Take, for example, Nvidia Optimus technology for laptops (which equipped particular models with 2 graphics cards to save battery life). It took some time for the linux community to finally create the bumblebee software (so linux users to choose which card is best for particular software).

                                                                                      4. Buy from a stable vendor- In order to compete with larger venders (like Dell, for instance), smaller companies often stuff their computers with cheaper hardware, which might not always work correctly on linux. Personally, my favorite hardware vender is Asus. Most of the time, their hardware works great with linux. 

                                                                                      5. Buy a back-up hard drive- This is just my personal preference. When you buy your computer, it will probably work out of the box with Windows. After installing linux, however, that might not be the case. Because of this, I will typically buy an extra hard drive with my computers and install linux fresh on that. If anythong goes wrong with the installation, I at least know that I have a usable windows PC to go back to. 

                                                                                      All that said, before you purchase your next computer, be sure to give a thought to linux.

                                                                                      Thanks for reading,
                                                                                      -Leios

                                                                                      Thursday, May 16, 2013

                                                                                      Web.by Web.py 2: Databases

                                                                                      Continuing from yesterday's post, today we will be using python to modify our site database(s). That being said, if you are new, you might want to check out the Apache web server, and your choice of either Postgresql or MariaDB for a database manager. Remember that python's primary purpose in the LAMP set-up is to communicate with both the web server and the database manager, meaning it will deal with most of the posting and getting back and forth. Like yesterday, we will start by starting the Apache and database manager daemons. From there, we will pull on the code from yesterday, which looked like this:


                                                                                      import web
                                                                                      render = web.template.render('templates/')
                                                                                      
                                                                                      urls = (
                                                                                          '/(.*)', 'index'
                                                                                      )
                                                                                      
                                                                                      class index:
                                                                                          def GET(self, name):
                                                                                              i = web.input(name=None)
                                                                                              return render.index(i.name)
                                                                                      
                                                                                      if __name__ == "__main__":
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()


                                                                                      With a /templates/index.html that looked like this:


                                                                                      $def with (name)
                                                                                      
                                                                                      $if name:
                                                                                          I just wanted to say <em>hello</em> to $name.
                                                                                      $else:
                                                                                          <em>Hello</em> world!


                                                                                      Again, we will be working off of this tutorial. First things first, we must tell web.py which database manager we are using by using something similar to the following line:


                                                                                      db = web.database(dbn='postgres', user='username', pw='password', db='dbname')


                                                                                      to be placed under the headers. If you wish to use MariaDB instead of Postgresql, simply replace "postgres" with "mysql." If you have not set up a username, password, or databasename, please refer back to my SoC posts about Postgres or MariaDB. In both cases, we finished the day in the same way: by accessing the database manager's admin interface. 

                                                                                      Now, let's create a simple "to do" list again, like we did the other day, except that we will be using our database managers and web.py instead of just Python. To do this, we must create a table in our databases called "todo." First, we must access our database manager's admin interface (assuming it is set up properly).

                                                                                      For Postgres:


                                                                                      $ psql -d myDatabaseName


                                                                                      For MariaDB:


                                                                                      $ mysql -u user -p'password' databasename


                                                                                      Once done, simply type (or copy and paste) the following lines:


                                                                                      CREATE TABLE todo (
                                                                                        id serial primary key,
                                                                                        title text,
                                                                                        created timestamp default now(),
                                                                                        done boolean default 'f'    );


                                                                                      This, is simply creating a table with the title "todo" with otherwise standard formatting. We can add a first line by typing:


                                                                                      INSERT INTO todo (title) VALUES ('Learn web.py');


                                                                                      Which inputs the phrase "learn web.py" into the table. I might suggest opening up a second terminal here to have access to both your admin database management and your code, because now we must go back to our code.py and alter the index.GET function to read our table:


                                                                                      def GET(self):
                                                                                          todos = db.select('todo')
                                                                                          return render.index(todos)


                                                                                      This is following the same format as yesterday. This time, though, we create a variable that uses the select function of our database to choose the "todo" table we just created. It will then return a rendering of that variable. We should also change the url scheme at the top of the file back to how it was:


                                                                                      '/', 'index',


                                                                                      Finally, to read the table, we must change our templates/index.html file to:


                                                                                      $def with (todos)
                                                                                      <ul>
                                                                                      $for todo in todos:
                                                                                          <li id="t$todo.id">$todo.title</li>
                                                                                      </ul>


                                                                                      Which uses python to select out the "todo" table within the variable "todos" we just created. We then use html to title each item and give it a line to itself. If you visit your site by running the code, you should see the phrase "Learn web.py", Which means we have successfully read from our database. Now, let's work on writing to it. In this case, we will add in any values we place in the url by adding in the following class:


                                                                                      class add:
                                                                                          def POST(self):
                                                                                              i = web.input()
                                                                                              n = db.insert('todo', title=i.title)
                                                                                              raise web.seeother('/')
                                                                                      


                                                                                      This is very similar to when we input our name yesterday, except now we are adding the data directly into the database. Of course, to do this, we must change the allowed urls to:


                                                                                      '/', 'index',
                                                                                      '/add', 'add'


                                                                                      Which allows for the subdirectory "add" with the class "add" in the url. 

                                                                                      Finally, we must add


                                                                                      <form method="post" action="add">
                                                                                      <p><input type="text" name="title" /> <input type="submit" value="Add" /></p>
                                                                                      </form>
                                                                                      


                                                                                      to the end of templates/index.html to allow posting through the site, itself. In full, your code.py should look like:


                                                                                      import web
                                                                                      render = web.template.render('templates/')
                                                                                      db = web.database(dbn='postgres', user='user', pw='password', db='dbname')
                                                                                      
                                                                                      urls = (
                                                                                          '/', 'index',
                                                                                          '/add', 'add'
                                                                                      )
                                                                                      
                                                                                      class index:
                                                                                          def GET(self):
                                                                                              todos = db.select('todo')
                                                                                              return render.index(todos)
                                                                                      
                                                                                      class add:
                                                                                          def POST(self):
                                                                                              i = web.input()
                                                                                              n = db.insert('todo', title=i.title)
                                                                                              raise web.seeother('/')
                                                                                      
                                                                                      if __name__ == "__main__":
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()
                                                                                      


                                                                                      And templates/index.html:


                                                                                      $def with (todos)
                                                                                      <ul>
                                                                                      $for todo in todos:
                                                                                          <li id="t$todo.id">$todo.title</li>
                                                                                      </ul>
                                                                                      
                                                                                      <form method="post" action="add">
                                                                                      <p><input type="text" name="title" /> <input type="submit" value="Add" /></p>
                                                                                      </form>
                                                                                      

                                                                                      Once done, run code.py one more time, and you should have a box that dynamically posts more data into your database. In my opinion, that's pretty cool. 

                                                                                      From here, you should have enough information about web.py to tackle some more code from their code samples and cookbook pages. We will probably return to web.py later, but for now we have done enough.

                                                                                      As always, thanks for reading.
                                                                                      -Leios.


                                                                                      Wednesday, May 15, 2013

                                                                                      Web.by Web.py 1: Tutorial

                                                                                      Yesterday, we created our first python program, a simple terminal "to do" list, today we are working with the web. In this example (spanning across two days), we will use the Apache Web Server and either the Postgres or MariaDB database manager. Click any of the above links to refer back to those posts in SoC. That being said, I will be working off of this tutorial (simply because it is the easiest one I found). If you have any questions, they might be answered on that page. Now, let's get to Web.py!

                                                                                      First things first, why web.py? Web.py is simple and extensible. As a developer, you can do many things with it that might be more difficult in other frameworks. At the same time, due to it's simple code base, it might be a little more difficult to use and set up. For that reason, it is a perfect candidate to cover first when working with web frameworks. Later, I might cover Django and some other web languages (such as PERL or PHP), if there is enough support.

                                                                                      To get started, make sure you have started your Apache (httpd) server and database manager's (either mysqld or postresql) daemon. Also make sure webpy is installed. Once done, we can begin working with our first web.py code. If you remember, at the head of most python code, there is a section to import important modules. In this case, in order to use web.py, we must import the "web" module:

                                                                                      import web

                                                                                      Once this is done, we must set up our urls using typical python fashion:

                                                                                      urls = (
                                                                                        '/', 'index'
                                                                                      )

                                                                                      Note that "urls" comes from the "web" module. Here we are setting up a simple url structure with an open primary directory ('/') and sing input class ('index'). In principle, we could name this class whatever we like, so long as we define it appropriately later:

                                                                                      class index:
                                                                                          def GET(self):
                                                                                              return "Hello world!"


                                                                                      In this example, we are defining the class index to use the "GET" function, with the "(self)" tag essentially defining the function to be self-consistent without any extraneous variables. The GET function has been seen previously in SoC, and is essentially a function to display information. Remember that the POST function is the opposite of this and allows us to indirectly modify our database.

                                                                                      Before running this code, we must set up the url structure so that web.py can understand what we are doing. In this case, we must add the following lines:

                                                                                      if __name__ == "__main__": 
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()        

                                                                                      These lines are essentially claiming that if we are on the mian page, the web application should run. We define "app" to run the application function within the web module and call a basic url structure and global calls for later use. We then run the app with "app.run."

                                                                                      To reiterate, the code should look like this:

                                                                                      import web
                                                                                      
                                                                                      urls = (
                                                                                          '/', 'index'
                                                                                      )
                                                                                      
                                                                                      class index:
                                                                                          def GET(self):
                                                                                              return "Hello world!"
                                                                                      
                                                                                      if __name__ == "__main__":
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()

                                                                                      Let's save this as "code.py" and run it like so:

                                                                                      $ python code.py

                                                                                      So long as your database manager is working appropriately, you should see a simple "Hello world!" message displayed when going to the linked site in any browser. Which is great! That means you are officially on your way to working with your own web server and site. If you want to choose which port (rather than the standard 8080), you can do the following:

                                                                                      $ python code.py 1234

                                                                                      Substituting "1234" with whatever numbers you like. Note that you might need to specify the use of python2 over python3. If that is the case, simply use this command:

                                                                                      $ python2 code.py


                                                                                      Now, let's work on some templating with HTML. First things fist, make a new directory called "templates," in this folder, create a file called "index.html." In this file, you can write any html code you want, but for now, let's just keep it simple:

                                                                                      <em>Hello</em> world!
                                                                                      

                                                                                      To call this file we need to go back to our code.py file and add in 


                                                                                      render = web.template.render('templates/')
                                                                                      

                                                                                      Under the first line. This calls the render function in the template function in the web module, which depends on a directory of your choice. In this case, that directory is "templates." The "render" function is essentially a python call for the data inside the file.

                                                                                      We then have to modify our index.GET function to allow access to the file we just created. By substituting in the following line:

                                                                                              return render.index()
                                                                                      

                                                                                      In the end, the code should look like this:

                                                                                      import web
                                                                                      render = web.template.render('templates/')
                                                                                      
                                                                                      urls = (
                                                                                          '/', 'index'
                                                                                      )
                                                                                      
                                                                                      class index:
                                                                                          def GET(self):
                                                                                              return render.index()
                                                                                      
                                                                                      if __name__ == "__main__":
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()
                                                                                      

                                                                                      When you run the code and visit the link in your web browser, you should see "Hello world!" But, let's say you want to have your site say hello to one person in particular. You could change the contents of templates/index.html to:

                                                                                      $def with (name)
                                                                                      
                                                                                      $if name:
                                                                                          I just wanted to say <em>hello</em> to $name.
                                                                                      $else:
                                                                                          <em>Hello</em> world!

                                                                                      In this case, you are using a mixture of python and html code, but because the index.html file is naturally html, you have "commented out" the python code with the "$" sign. In this file, you are assuming that the variable "name" has been defined in code.py, and defining this file with that variable. You are then giving a simple if, else statement. If the site is visited with the variable "name" specified, the text will display, "I just wanted to say Hello to [name]." Otherwise, it will read exactly what it did last time.

                                                                                      To get this to work, we must change our code.py file in a few ways. First, we must make the index.GET funtion a function of "name." second, we must imput a name. In order to do this, we must modify the index class to read:

                                                                                      class index:
                                                                                          def GET(name):
                                                                                              i = web.input(name=None)
                                                                                              return render.index(i.name)
                                                                                      

                                                                                      The line "i = web.input(name=None)" means that we are defining a new class "i" with contents determined by the browser url. If you run the code and visit the url at /?name=Joe, then the site will say hello to Joe.To simplify this url a little, we might want to change the url line at the top to read: And change the index.GET function to be a function of both "self" and "name," like so: Once done, your code should look like this: 

                                                                                      '/(.*)', 'index'

                                                                                      And change the index.GET function to be a function of both "self" and "name," like so:

                                                                                      def GET(self, name):

                                                                                      Once done, your code should look like this: 

                                                                                      import web
                                                                                      render = web.template.render('templates/')
                                                                                      
                                                                                      urls = (
                                                                                          '/(.*)', 'index'
                                                                                      )
                                                                                      
                                                                                      class index:
                                                                                          def GET(self, name):
                                                                                              i = web.input(name=None)
                                                                                              return render.index(i.name)
                                                                                      
                                                                                      if __name__ == "__main__":
                                                                                          app = web.application(urls, globals())
                                                                                          app.run()
                                                                                      

                                                                                      If you run the code, your site should read "Hello world!" initially, but when visited from the /Joe url, it will say hello to Joe. Tomorrow, we will work directly with databasing, wich can be somewhat challenging.

                                                                                      As always, thanks for reading.
                                                                                      -Leios

                                                                                      Tuesday, May 14, 2013

                                                                                      Perilous Python Project 1

                                                                                      If you remember back to the first day of SoC, we wrote a small "hello world" code in Python, and it happened to be tied with lua for the simplest code. That being said, if Python is your first true coding experience, you might expect some challenges, but it certainly should not be as difficult as C/C++ or Java to learn. In our case, there are quite a few web frameworks that work with python (notably Django and web.py), which makes the language somewhat more important. That being said, lets start by creating a simple terminal program that allows you, the user, to read the contents of a "to do" list. This will be a combination of Python and Bash scripting, but it shouldn't be anything too difficult and should be good practice in approaching any coding project.

                                                                                      Step 1: Decide how you want the program to run

                                                                                      Personally, I would like a simple terminal command that prints out everything I have saved in my "to do" list. For that, I'll need the command itself, a file for that command to call, and the "to do" list. That makes three files.

                                                                                      Step 2: Create the "to do" list

                                                                                      Honestly, you don't have to write anything in it, you just have to make the file. To do this, just open up the file in any text editor you want and save it, possibly with an item you want to do later. For the sake of this example, let's call the file "list"


                                                                                      $ nedit list


                                                                                      I used nedit here because it seems the most straightforward to use. You could also use Vi/Vim, NaNo, Joe, or whatever you like. Enter something to do in the first line, if you like, like "learn to code" so your file reads simply this:


                                                                                      Learn to code


                                                                                      And there you have it. This is your "to do" list.

                                                                                      Step 3: Create a Python file

                                                                                      Now we want to call this file in python, so how would we do that? Well, let's create a python file called todo.py that reads:


                                                                                      import shutil
                                                                                      import sys
                                                                                      with open("/home/user/list", "r") as f:
                                                                                          shutil.copyfileobj(f, sys.stdout)
                                                                                      

                                                                                      This file is importing the "shutil" and "sys" modules from the standard python library. Let's go over each of these individually:

                                                                                      shutil- this module offers a number of high level operations for file manipulation outside of the python code. In this case, we need to open the "list" file we just made, and copy it to the terminal (stdout). As far as file manipulation is concerned, this one is rather easy.

                                                                                      sys- This gives the user access to some variables maintained by the interpreter. This means that it allows access to statistical information and terminal rights. In this case, we use it to envoke the terminal to print out information--namely our "to do" list.

                                                                                      The next line opens our file "/home/user/list" and reads it (which is what the "r" is for). After that, it assigns the list a value of "f". The colon, ":", indicates the next line is dependent on the first. That line calls the shutil module "copyfileobj" and copies "f," our list, to "sys.stdout," which is the terminal. 


                                                                                      Step 4: Create your command

                                                                                      At this point in the process, you should be able to call todo.py like so:


                                                                                      $ python todo.py


                                                                                      Output:


                                                                                      Learn to code


                                                                                      Which means everything we have done so far is working. That being said, It's a bit cumbersome to type in that command every time. Instead, let's create another file, "todo," with the following contents:


                                                                                      python /home/user/todo.py


                                                                                      Once saved, we need to give this command executable rights:


                                                                                      # chmod +x todo


                                                                                      This means that our new command to see the list is"


                                                                                      ./todo


                                                                                      But that's still not enough! I don't want to see that annoying "./" term every time I want to check out my "to do" list! So I'm going to copy the file into my /usr/bin directory like so:


                                                                                      # cp todo /usr/bin


                                                                                      you might have been wondering why we have been using the full directory tree with "/home/user/" fully typed out when calling the files. This is so that no matter where we are in our directory tree, we can call our todo list by simply typing:


                                                                                      $ todo


                                                                                      Which is kinda cool.

                                                                                      Step 5: Echo in contents

                                                                                      Now, let's say you are on the run and you just remembered about your dentist appointment later that afternoon. You might not have time to go into your file and add in a new line for "Go to the Dentist." What should you do?

                                                                                      Well, there's a command just for that. It's called the "echo" command. If you want to add a new line to your file, just execute:


                                                                                      $ echo "Go to the Dentist" >> /home/user/list


                                                                                      and next time you use the "todo" command, thre should be a new line reading "Go to the Dentist". Unfortunately, the easiest way to remove content from your todo list is to go into the file and remove it yourself.

                                                                                      Regardless, your "to do" list is done! Woo!

                                                                                      Final Notes About Python:

                                                                                      Python is a modular language, meaning it is dependent on standard libraries of code. That being said, you are able to import your own python files whenever you like with the "import" command at the head of every file (much like we did with "shutil" and "sys" in today's example).

                                                                                      Outside of that, we will definitely return to do more python tasks later, but we should have enough information to cover a simple web.py tutorial, which will be saved for tomorrow.

                                                                                      Until then, Thanks for reading.
                                                                                      -Leios

                                                                                      Monday, May 13, 2013

                                                                                      How To Make Love [HTML] Online

                                                                                      Now, I know what you are thinking: "I learned HTML ages ago! Why are you wasting your time with it now?" Well, you are either thinking that or, "What the ---- is up with the title?" Either way, today we cover some basics of HTML. In some ways, the language is the most important one to know, because it is the one that clients actually see when viewing your site. That being said, even if you have the most sound and secure servers in the world, it helps to have a pretty site. A few days ago, we edited /srv/http/index.html and viewed http://localhost/ to see our changes. For today's purposes, we can do the very same thing to check out our HTML code. If you don't remember how we viewed our localhost, be sure you have set up your Apache server, and then start the daemon. In Arch, this can be done by:


                                                                                      # systemctl start httpd


                                                                                      In Ubuntu:


                                                                                      # service httpd start


                                                                                      Once done, visit http://localhost/. It should be ready to go. If you followed A Patchy Apache, it should read:


                                                                                      If you didn't, it should display some boring filesystem. If you want it to disply our fancy "Hello World!," just edit your /srv/http/index.html to read:

                                                                                      <html>
                                                                                      <title>Welcome</title>
                                                                                      <body>
                                                                                      <h2>Hello World!</h2>
                                                                                      </body>
                                                                                      </html>


                                                                                      We might as well start with this for out HTML introduction. As you might have noticed, the file starts with the <html> tag, letting the web server know which language to call. The next tag is the <title> tag. This will alter what clients read on their tab for the site. In our case, it reads "Welcome," but we could change it to read whatever we like. Like many other languages, the next logical step is the <body> tag, which is the bulk of the HTML code. The <h2> tag can be interpreted to mean "header 2" or "the header of the body." We could have used any header tag, ranging from h1 to h6, but h2 was chosen for this example. Finally, the file ends by closing each domain, wich is done by adding a "/" to the original tag. For example, <body> is closed by </body>. If you have never seen HTML code before, this might be a bit cumbersome, but trust me when I say that HTML is relatively easy to learn.

                                                                                      To show some variation to the language, you could imagine changing the "Hello World" example to read "Welcome to KeroCG.com!" in the title and "Today we are learning about HTML. Care to join us?" in the subtext by using the following alterations:


                                                                                      <html>
                                                                                      <title>KeroCG.com</title>
                                                                                      <body>
                                                                                      <h1>Welcome to KeroCG.com!</h1>
                                                                                      Today we are learning about HTML. Care to join us?
                                                                                      </body>
                                                                                      </html>
                                                                                      


                                                                                      If you copy this to your /srv/http/index.html, your http://localhost/, should look like this:


                                                                                      Now on to some fun stuff. Let's say you want to add a link in your text. It goes something like this: <a href="link">text to click on</a>. For example, if you wanted to link KeroCG.com as the premier place to learn how to code, you would type in: <a href="kerocg.blogspot.com">The best place to learn to code</a>. This would create a link between the words "The best place to learn to code" and "kerocg.blogspot.com." If you wanted to color some text or change the font type, you can do that by adding the "font color=color" or adding "font face=font" to your tag. Note that the color chosen for your font can be a hexadecimal code. Also, italics, bold, and underline are <i>,<b>, and <u> respectively. <p> creates a new paragraph. So, let's change our code:


                                                                                      <html>
                                                                                      <title>KeroCG.com</title>
                                                                                      <body>
                                                                                      <h1>Welcome to KeroCG.com!</h1>
                                                                                      Today we are learning about HTML. Care to join us?
                                                                                      <p><i>italics</i>
                                                                                      <p><b>bold</b>
                                                                                      <p><u>underlined</u>
                                                                                      <p><font color = "blue">Blue</font>
                                                                                      <p><font face = "courier">Courier</font>
                                                                                      <p><a href="kerocg.blogspot.com">The best place to learn to code</a>
                                                                                      </body>
                                                                                      </html>
                                                                                      



                                                                                      This will change your http://localhost/ to read:

                                                                                      And we are well on our way to working with some real html code. Imagine you wish to change the background, this can be done by adding the following tag of code: <background="backgroundimage"> for example, if you wanted to make this image (full credit to ringosdiamond from deviantart.com) your background, you would save it in your /srv/http/ directory and add the following line to your code: <background="Wallpaper____TARDIS_by_ringosdiamond.png"> after your body tag. You can manipulate this background by adding in a few variables, such as "bgcolor=color" or "bgproperties="fixed."" remember that your chosen color can be a hexadecimal code.

                                                                                      Now, we will probably come back to HTML later (after working a little with web.py), but for now, we will just work a little on tables and framesets. Firstly, tables. Tables in HTML use the <table> tag. They also use the <tr> and <td> for manipulating table rows and table data respectively. For example, if you wanted to create a simple table with 2 colums and 3 rows (along with the aforementioned background image), you could add the following lines to your code:


                                                                                      <html>
                                                                                      <title>KeroCG.com</title>
                                                                                      <body background="Wallpaper____TARDIS_by_ringosdiamond.png">
                                                                                      <h1>Welcome to KeroCG.com!</h1>
                                                                                      Today we are learning about HTML. Care to join us?
                                                                                      <p><i>italics</i>
                                                                                      <p><b>bold</b>
                                                                                      <p><u>underlined</u>
                                                                                      <p><font color = "blue">Blue</font>
                                                                                      <p><font face = "courier">Courier</font>
                                                                                      <p><a href="kerocg.blogspot.com">The best place to learn to code</a>
                                                                                      <p><table border="1">
                                                                                      <tr>
                                                                                      <td>cell1</td>
                                                                                      <td>cell2</td>
                                                                                      </tr>
                                                                                      <tr>
                                                                                      <td>cell3</td>
                                                                                      <td>cell4</td>
                                                                                      </tr>
                                                                                      <tr>
                                                                                      <td>cell5</td>
                                                                                      <td>cell6</td>
                                                                                      </body>
                                                                                      </html>
                                                                                      

                                                                                      Which provides:



                                                                                      Now, let's say you want to have two (or more) partitions to your site, to allow a navigation bar or something on the side with a host of links. This can be done by creating frames, which are like tables, except they take up the whole screen. We could split the screen directly down the middle and add content to both dies individually by adding this to our code:

                                                                                      <frameset cols="50%,50%">
                                                                                        <frame>
                                                                                        <frame>
                                                                                      </frameset>


                                                                                      You can manipulate the contents of the frames by linking in other sites. Be sure these sites are saved to the appropriate directory. To do this with http://localhost/, use the cp command to copy your current index to another file, say index2.html.


                                                                                      # cp index.html index2.html


                                                                                      And then save the following to index.html:


                                                                                      <frameset cols="50%,50%">
                                                                                        <frame name="index" src="index2.html">
                                                                                        <frame>
                                                                                      </frameset>


                                                                                      If you did so, you should see a site that looks like this:


                                                                                      But that's not quite aesthetically pleasing. Instead, let's create a sidebar, side.html:

                                                                                      <html>
                                                                                      <title>KeroCG.com</title>
                                                                                      <body bgcolor="333333">
                                                                                      <font color = "white">HTML</font>
                                                                                      </body>
                                                                                      </html>


                                                                                      And then change index.html to this:

                                                                                      <frameset cols="10%,90%">
                                                                                        <frame name="index" src="index2.html">
                                                                                        <frame>
                                                                                      </frameset>


                                                                                      Then your http://localhost/ will look like this:


                                                                                      And there you have it, a simple guide to HTML. We can come back to it later if there is enough support

                                                                                      As always, thanks for reading, and be sure to check out Ringosdiamond at deviantart.com,
                                                                                      -Leios

                                                                                      Sunday, May 12, 2013

                                                                                      404 error: Posts not found!

                                                                                      Unfortunately, due to a weeked spent at the lake with my dear mother (you know, for Mother's Day and all), I did not have access to the internet, which meant I could neither post nor learn about Python and Web.py like I said I would. That being said, I have spent the past hour looking over the material again and feel I need a refresher on HTML first. So, here is the posting schedule for the upcoming week:

                                                                                      Monday: How To Make Love [HTML]
                                                                                      Tuersday: Python Peril
                                                                                      Wednesday: Web.by Web.py
                                                                                      Thursday: Advanced Web.py
                                                                                      Friday: Linux Hardware Options
                                                                                      Saturday: Linux Viruses: Fact or Fiction?
                                                                                      Sunday: A Window to Windows: Linux Options

                                                                                      As a bit of an apology for missing the past few days of SoC, I have attempted to draw a Kerosene-Powered Cheese Grater:

                                                                                      In the future, I will do what I can to inform you guys a few days beforehand when I may or may not be unable to post.

                                                                                      As always, thanks for reading,
                                                                                      -Leios

                                                                                      Friday, May 10, 2013

                                                                                      The Database Manager Formerly Known as MySQL

                                                                                      Oracles are kind of cool. Sure, they aren't around anymore, but in olden times they were known for wise counsel and prophetic visions. Anyone who makes a living by instilling vague truths and rumors onto their audience is okay in my book; however, Oracle, the company, seems to have a knack for plucking fantastic open-source software and closing it off to developers. Anyone who makes a living doing that is not okay in my book. I do not mean to antagonize them, but a few years ago, they took OpenOffice, and now they have MySQL--the cherished Database Manager that everyone knows and loves. Of course, rather than whining about it, the linux community evolved the two projects into LibreOffice and MariaDB, respectively, so no incredible harm was done. 

                                                                                      In the case of MariaDB, the developers decided to keep all of the old commands from MySQL, meaning that practically anything you could do with MySQL, you can do with MariaDB while still believing you are using MySQL. That being said, after installing MariaDB on your system, you might as well find a MySQL guide to follow to  get to your database management utilities (like we did at the end of yesterday's post). Firstly, install MariaDB on your system and start the daemon. In Arch, this can be done  with:

                                                                                      # systemctl start mysqld

                                                                                      In Ubuntu:

                                                                                      # service mysqld start

                                                                                      Afterwards, run the secure installation:

                                                                                      # mysql_secure_installation

                                                                                      This will give you an interractive set-up that is quite easy to follow. Remember that your MariaDB root and local root are different. If I were you, I would assign different passwords to each. If you are ever in doubt of how to answer a question, go with the most secure option. You can always change it later. Once done, you have effectively set up MariaDB and can log in to your MariaDB root account with:

                                                                                      $ mysql -p -u root

                                                                                      Which is all fine and dandy, but how do you access a database from a non root user? Well, the next steps will get you there. First, once you are logged on as root, type in the following command:

                                                                                      # create database databasename;

                                                                                      This, as implied by the script, creates a database with a name "databasename." From here, we will give your local user permission to use that database and set an appropriate password:

                                                                                      # grant usage on *.* to user@localhost identified by 'password';
                                                                                      

                                                                                      Now we need to grant all privileges to your local user:

                                                                                      # grant all privileges on databasename.* to user@localhost;

                                                                                      And that's that. You can log on to edit your database with:

                                                                                      $ mysql -u user -p'password' databasename

                                                                                      And now we have set up both Postgresql and MariaDB as database managers. In the posts to come, you can use whichever database manager you wish. Tomorrow, we will work on Python some more before moving to our first web framework, web.py! 

                                                                                      Thanks for reading,
                                                                                      Leios

                                                                                      Thursday, May 9, 2013

                                                                                      Posting in Postgresql

                                                                                      As mentioned in Tuesday's post, MySQL (now known as MariaDB) is often chosen over Postgresql as a database manager, but Postgres definitely has it's advantages.  At least in my experience, Postgresql is much easier to set up than MySQL and has plenty of features that make it simple and fun to use. That being said, let's get started!

                                                                                      On installation of postgresql, the user "postgres" is created. For future reference, when you are asked to "become the postgres user," it means to use the following command:


                                                                                      sudo -i -u postgres


                                                                                      Which logs you on as the postgres user. When there, you might want to set up a pasword by typing "passwd," but this is not necessary for now. First, we must set up a directory for the postgres user to use as it's base of operations. This can be done in three steps:

                                                                                      1. Create the temporary files for /run/postgresql:


                                                                                      # systemd-tmpfiles --create postgresql.conf


                                                                                      2. Create a data directory:


                                                                                      # mkdir /var/lib/postgres/data


                                                                                      3. Give the postgres user ownership of that directory:


                                                                                      # chown -c -R postgres:postgres /var/lib/postgres


                                                                                      We can now become the postgres user and start our database:


                                                                                      $ initdb -D '/var/lib/postgres/data'


                                                                                      once done, we should start the postgresql daemon:


                                                                                      # systemctl start postgresql


                                                                                      And now Postgres is up and running! That being said, it is a good idea to create another user under the postgres user to manipulate individual databases. This can be done interactively by:


                                                                                      $ createuser -s -U postgres --interactive


                                                                                      More often than not, this new user is identical to the user you typically use on your system, but it doesn't have to be. Once you have the user set up, be sure you are logged in as the new user and create your database:


                                                                                      $ createdb myDatabaseName


                                                                                      Now for the fun stuff. We can directly modify our database by using the postgresql database shell:


                                                                                      $ psql -d myDatabaseName


                                                                                      We will definitely use this when working with web.py later in the week, but for now, here are some simple commands:

                                                                                      Connect to a database:


                                                                                      => \c <database>


                                                                                      List all users and their permissions:


                                                                                      => \du


                                                                                      Display a summary of all the tables:


                                                                                      => \dt


                                                                                      Quitting the shell (same for other shells similar to this one)


                                                                                      => \q or ctrl+d


                                                                                      We may come back to Postgres when configuring it to work with remote hosts or performing maintenance, but before that, we will take a look at MariaDB and then get to work on some basic site design!

                                                                                      Thanks for reading,
                                                                                      Leios