i0L6o

            Miks käsuakendel (CLI) on tavaliselt must taust?
            Sest pimedas pole midagi näha:

            Pimeda metafoor aitab õppida Unixi käske.

MÄRKMED UNIXi ALUSTE KOHTA
--------------------------

Alltoodud jutt tundub autorile oluline.

Lisad pole õppimiseks, kuid pigem selleks, et poleks vaja keset õppetundi neid algkoode liiga kaua otsida.

PRIORITEEDID
------------

Kui ei mõista asju, mis peavad paiknema null-korrusel, siis pole mõtet tegeleda nendel põhinevate asjadega ülemistelt korrustelt -- See pole alati nii, kuid kunagi seda usuti, kuna see tõde paistis välja üsna loogilisena (Star Trek 1966, Mr Spok (vulkaanlane): it seems logical..)

Siis üks tark ütles: see on tähtsamast tähtsam.. Tegelikult see polnud nii, ta lihtsalt tahtis, et teda kaua mäletatakse. Siis tuli teine, kolmas, 10000-s -- kõik sama jutuga. Siis tuli veel üks, kuid ei öelnud, et jutt on oluline (kuna keegi poleks teda uskunud niikuinii).

Möödus 40 aastat ning aeg pani paika, mis oli rohkem oluline ja mis vähem. Lühike sissejuhatus 2000 leheküljel ei näe enam paksem välja 30 leheküljelisest juhendist aastast 1978 (ma mõtlesin praegu "Awk -- A Pattern Scanning and Processing Language" by Aho, Kernigan, Weinberger). Soovid lugeda korgist korgini? -- alusta kogu Web'i lugemisest:)

USSIAUK (WORMHOLE)
------------------

Suvalist informatsiooni võib esitada: '0' '1' ja ' ' abil (Alan Turingu masin,  Н. П. Брусенцов и Сетунь). Arendades teooriat Turingu masina abil üsna varajasel etapil jõuame 'prioriteedi' mõisteni -- antud juhul võime ehitada arvutit, mis töötab kasutades ainult 0 ja 1, kuid kolmas komponent ei kao kuhugi, nüüd ta esineb 't ehk time', '[x] ehk do not care', 'slice (baiti või sõna pikkus)', ning teiste nimetuste all.

[01x] abil seletame digitaaltehnika kombinatsioonskeeme, [01t] automaate (state machine), jne. Kuid see on kõik, nii öelda, 'Before Unix'.

Meie esimene probleem on lihtne. Kasutades ainult 0 ja 1 kirjutada 'TERE MAAILM!'. Kus lõppeb üks täht ning algab järgmine? Tuleb panna paika, et iga sümboli jaoks kasutame teatud pikkusega lõiku. Näiteks, meie bait on viie bitine (eesti tähestik võõrtähtedega, ehk 'extended' ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜXY ):

  00000:A 00001:B 00010:C 00011:D 00100:E 00101:F 00110:G 00111:H
  01000:I 01001:J 01010:K 01011:L 01100:M 01101:N 01110:O 01111:P
  10000:Q 10001:R 10010:S 10011:Š 10100:Z 10101:Ž 10110:T 10111:U
  11000:V 11001:W 11010:Õ 11011:Ä 11100:Ö 11101:Ü 11110:X 11111:Y

Kas 16 4 11 4 c 0 0 8 b c meeldib? Ei meeldi, see on TEREMAAILM (tühikut pole, hüüumärk puudub). Kuid uute sümbolite ( {SPACE}, '!') jaoks meie tähestikus pole enam ruumi. Nüüd tähtis moment:

  ÜHTE VÄHEMKASUTATAVAT SÜMBOLIT KASUTAME USSIAUGUNA (WH, WORMHOLE) --
  LÄBIPÄÄSUNA UUE TÄHESTIKU JUURDE (UUELE KORRUSELE):

Tagasi 0 korrusele saame automaatselt, niipea kui üks sümbol on valitud. Näiteks X asemel on meil ussiauk (X ise on nüüd uuel kohal esimesel korrusel):

  floor 0: ABCDEFGHIJKLMNOPQRSŠZŽTUVWÕÄÖÜ{WH}Y
  floor 1:  !X{WH} .. {RESERVED} ..
  ..
  floor n: {{WH}RESERVED} ..

Nüüd meeldib rohkem:

  10110 00100 10001 00100 11110 00000 01100
  00000 00000 01000 01011 01100 11110 00001

  ehk 16 4 11 4 1e 0 0c 0 0 8 b c 1e 1
  ehk TERE{WH}{SPACE}MAAILM{WH}!
  ehk TERE MAAILM!

Unix and 'escaping with backslash'
..................................

  USE '\' AS WORMHOLE IN UNIX
  (tradition).

Inimene kipub vigu tegema, tasub vaadata üle, kuidas see harjutus näeks välja programmi kujul (lisa A).

VAIKEVÄÄRTUS (DEFAULT VALUE)
----------------------------

Terminalis me suhtleme arvutiga käskude abil, olles sellega aktiivne pool dialoogis. Üldjuhul käsk koosneb võtmesõnast ning parameetritest (arguments). Kui argumente pole esitatud, Unix'i käsk võib:

  1. Näidata lühikest kasutamisjuhendit

      $ man
      What manual page do you want?
      $

  2. Neelata käsk vaikides, kuid tingimata tagastada kontrolli

      $ echo
      $

  3. Võtta kasutusele argumentide vaikeväärtusi
     ('head' vaikimisi näitab 10 esimest rida)

     $ ls -1 | cat -n | head
      1  apps
      2  C
      3  CB
      4  CM60S
      5  Desktop
      6  Documents
      7  Downloads
      8  Flowgorithm
      9  Hello
     10  Music
     $

Argumendid võivad olla positsioonilised või nimelised. Kui teil on vaja muuta vaikeväärtust AINULT kolmanda positsioonilise argumendi jaoks, tuleb 1-se ja 2-e positsiooni argumentide vaikeväärtused sisestada selgesõnaliselt (explicitly). aplusb.c lähtekood on toodud lisas B.

  $ aplusb
  1+2=3 (defaults were 1 2)
  $ aplusb 5
  5+2=7 (first arhument value reassigned)
  $ aplusb 1 10
  1+10=11 (both arguments values reassigned)
  # PHP style have it's roots in C strtol()
  $ aplusb 4monkeys 3potatoes
  7

named arguments are prefixed with '-' and are in one of the 4 formats:

  default was 0 or false                        default is not 0
  short explicit: -x 5       x is 5             x is 5
  short implicit: -x         x is 1 (true)      illegal
  long  explicit: --xval 4   xval is 4          x is 4
  long  implicit: --xval     xval is 1 (true)   illegal

MÜRGITAMINE (POISONING)
-----------------------

Juhul kui on määratud ainut üks prioriteedi tase, tihti head ideed mürgitatakse, peites ennast idee arendamise eesmärgi taha.

Näide 1: dubleeriv -e võti veaga:

  $ cat poi
  #!/bin/bash

  A=X
  echo "$A<TAB>$A"
  A=XXX
  echo "$A<TAB>$A"
  echo -e "$A\t$A"
  echo "line one
  line two"
  echo -e "line one\nline two"

  $ sh poi
  X       X
  XXX     XXX
  -e XXX  XXX
  line one
  line two
  -e line one
  line two

TEKSTI REDAKTORID NING SKRIPTIMINE
----------------------------------

Skriptid sobivad selleks, et automatiseerida korduvaid ülesandeid. Kuna kursuse nimes on mainitud sõna haldus (Linux / BSD operatsioonisüsteemide haldus (administration)) siis me peame tundma ennast mugavalt # prompti taga (root user ehk administraator), ning oskama ülesande lahendusi dokumenteerida ja automatiseerida. Kõige tühisemat probleemi tuleb osata lahendada ja esitada skriptina.

Näide
.....

"Create 2 main partitions occupying whole HD: swap and ext4 (flag 'active') type.  Swap partition size should be 1GiB. Partitioning table type should be MBR (options are AIX, AMIGA, BSD, DVH, GPT, MAC, MSDOS, PC98, SUN, LOOP where MBR means MSDOS). Mount ext4 on /mnt/sdb2, activate swap."

Kasutame käsurea tööriistu, mis võimaldavad skripteerimist. Dokumentatsiooniks on skript ise. Sellist dokumenti oskavad lugeda arvuti ja spetsialist. Kasutaja võib õppida seda lugema foorumitel, man lehekülgedest jne. Skripti kood -- vaata lisa C.

Alustasin skripti kirjutamist, ning kohe esimestel minutitel -- 'bug' echo käsus.

  !!! BUG DISCOVERED 20171223
  # cat bug
  #!/bin/bash
  echo -e "buggy"
  # sh buggy
  -e buggy

  workaround:
  echo -e "buggy" | sed 's/^-e //'

Kui juhtub midagi sarnast, mind alati huvitab, kuidas sellist asja on võimalik mitte märgata ligi 50 aasta jooksul. Installime ajamasinat ning hüppame aastasse 1978:

  $ sudo apt-get install simh
  $ wget -c ftp://ftp.uk.freesbie.org/sites/www.bitsavers.org
                /simh.trailing-edge.com_201206/kits/uv7swre.zip
  $ unzip uv7swre.zip
  $ cat u7
  set cpu 11/45
  set tto 7b
  att rl unix_v7_rl.dsk
  boot rl
  $ pdp11 u7
  @boot
  : rl(0,0)rl2unix
  # man echo
  ..
  NAME
       echo - echo arguments
  SYNOPSIS
       echo [ -n ] [ arg ] ...
  ..
  # kill -1 1
  ^E
  Simulation stopped, PC: 002306 (MOV (SP)+,177776)
  sim> quit
  Goodbye

OK. Vanasti -e puudus. Seda oligi vaja teada saada.

  # echo "line 1
  > line 2"
  line 1
  line 2

Skriptid tihti sisaldavad sed voofiltrit, mis on ed ja red teksti redaktoritega üsna sarnane.

Ed sobib kokku erinevate copy-paste meetoditega. Näiteks meil on järgmine fail nimega 'report' kuhu on järjest kirjutatud kõik KASUTAJA klahvi vajutused enne ed sessiooni, sessiooni ajal, ning peale seda.

  touch l02
  ed l02
  a
  line one
  line two
  line three
  .
  ,s/line/row/
  ,n
  2p
  s/two/kaks/
  1a
  row one-and-a-half
  .
  ,p
  w
  q
  mv l02 straße_zwei
  cat -n straße_zwei
  rm straße_zwei

käivitame faili käsuga

  cat report | sed 's/^  //' | bash

Nagu näha, kõik on tehtud automaatselt, sekkuda polnud vaja.

HOIATUS. nii ed kui ka vim redaktorite (vim-tiny esialgu töötab) negatiivseks küljeks on see, et täiesti trükitavad sümbolite kombinatsioonid võivad ootamatult moonutada torust saadavat (piped) teksti: '.\n' -- ed, autoident teatud failitüüpidega -- vim.

ED AND RED TRICKS
-----------------

  n  -- print with numbers
  s  -- search and replace by regexp
  a  -- append, enter insert mode,
        the only way to insert at the top
  i  -- insert line,  enter insert mode
  c  -- change line, enter insert mode
  .  -- exit insert mode
  d  -- delete line
  p  -- make line current and print it
  w  -- save
  q  -- quit
  !  -- execute shell command
  u  -- undo
  Q  -- quit without save

  scope by example

    top line     -- 1
    bottom line  -- $
    current line -- default

    3n  -- print line number 3 with line number
    n   -- print current line number with line number
    0a  -- append on top of the file
    5,7 -- print lines from 5 to 7
    1,p -- print from top to current line
    ,$p -- print from current line to the end of file
    ,n  -- print whole file, enumerate lines
           ( 1,$n 'long' way or %n 'modern' (1980+) way)

REGULAARAVALDISED
-----------------

Teema on väga põhjalikult kajastatud internetis. Soovitan näiteks

  1. Ryan's Tutorials

    https://ryanstutorials.net/

  2. The Grymoire..

    http://www.grymoire.com/

Regulaaravaldiste roll Unixis (ja mitte ainult) on väga suur. ?ed, awk, bash, vim, isegi nano, enamus programmeerimiskeeli võimaldavad kasutada regulaaravaldisi. Kui neid vältida, tuleb teha enda kätega rutiinseid operatsioone -- tulemus võib tulla sarnane, kuid 50 aastat hiljem ning vigadega.

C + Regex + Windows
...................

Tihti juhtub nii, et kompileerides lihtsat koodi Windowsi all (Annex D) üllatume kompilaatori vastusega

  re.c:2:19: fatal error: regex.h: No such file or directory
   #include <regex.h>
                     ^
  compilation terminated.

Reaktsioon võib olla erinev, alates "Tingimata tahad C ja Regex koos? Loobu Windows OS'ist", kuni "midagi pole kirjutatud, kirjutan ise".

  git clone https://github.com/kokke/tiny-regex-c

või

  git clone https://github.com/cesanta/slre

Rahulikuma reaktsiooni puhul leiame

  g++ -std=c++11 or -std=gnu++11 ..

KÄSUD JA VOOD
-------------

Käske tuleb sortida ning määrata neile prioriteete: asendamatu, oluline, kiirendab tööd, ei sega.. Kõige olulisemat informatsiooni tähtsamate käskude kohta leiab siit:

   TLDR Pages -- A Simplified alternative to Unix/Linux man pages

   https://www.unixmen.com
     /tldr-pages-simplified-alternative-unixlinux-man-pages/

   http://tldr.sh/

Tihti käske ühendatakse omavahel torude abil.

Kuidas neid kasutada Debian linuksis:

  $ sudo apt-get install nodejs npm
  $ sudo npm install -g tldr

Olulisemad käskude kategooriad on:

  install                  filters
  files and folders        users
  file attributes          processes
  streams                  boot
  archives                 network
  file systems             programming
  text editors             miscellaneous

Olulisemad käsud on:

  echo        cmp         grep          ps             dig
  clear       diff        tr            kill           hostname
  env         patch       sed           killall        dnsdomainname
  expr        find        awk           top            service
  free        ----        ----          nice           systemctl
  od          tee         more          job            ----
  xxd         tar         head          fg             gcc
  printf      cpio        tail          bg             gdb
  seq         gzip        sort          ----           make
  if          ----        uniq          dmesg          strip
  test        fdisk       paste         uname          ----
  for         mkfs        wc            init           apt
  while       mkswap      ----          ----           dpkg
  date        fsck        chown         lsmod          ----
  time        ----        chgrp         insmod         lspci
  ----        dd          chmod         modprobe       lsusb
  pwd         df          useradd       rmmod          ld
  ls          du          userdel       ----           ldd
  mkdir       mount       passwd        ssh            sync
  cd          umount      su            wget           swapon
  cp          ----        sudo          ping           swapoff
  mv          vi          chroot        ip             ----
  rm          ed          which         ifconfig       mkfifo rm*
  ln          nano        who           route          >   >>  2>  2>&1
  touch       emacs       whoami        traceroute     <   <<
  cat         ----        ----          nslookup       |   tee

------
*) rm pipe_name

   .. but , the next time when i am executing the script
   i am getting an exception like

    "mkfifo: cannot create pipe_name: File exists"

   https://www.unix.com/hp-ux/79454-remove-named-pipes.html
------

Selleks, et nendega paremini tutvuda:

  1. Näidake alltoodud käsud kujul

      nr. kategooria::käsk

  2. Näidake tärniga, kas käsk eksisteeris juba Unix v7 aastal 1979.
     Millised võtmed (argumendid) on näidatud "TLDR man pages"
     dokumendis, kuid puuduvad Unix v7, kas nad tunduvad olema
     asendamatud?

  3. Kirjutage skript, mis valmistab "TLDR man pages" programmi
     ja näidatud nimekirja põhjal ühte pikemat tekstifaili.

Näited

1. Kuidas saata X-teenuse abi terminalile?

     $ X --help 2>&1 | less

2. Lihtne linux: kernel + busybox.
   Kui palju käske sisaldab busyboxi installitud versioon
   (Ubuntu Bionic 18.04 LTS)?

     $ busybox | sed -n -e '1,/^Currently/!p' | wc -w
     254

FAILID JA KAUSTAD
-----------------

  Sageli külastatavad kohad:

  /bin   -- käsud, mida näevad kõik kasutajad ($PATH)
  /sbin  -- käsud, mida näeb root kasutaja
  /boot  -- alglaadimine (tuum (kernel), grub..)
  /dev   -- block and sequental devices (seadmed*)
  /etc   -- konfiguratsioon failid
  /home  -- kasutajate kodukaustad (/home/õpilane..)
    /home/username/.local/bin -- neljas korrus
  /lib   -- teegid (libraries)
  /mnt   -- mount points (/mnt/cdrom, /mnt/sdg1, /mnt/vbox..)
  /proc  -- in RAM
  /root  -- root kasutaja kodukaust
  /tmp   -- ajutised (temporary) failid
  /usr   -- teine korrus
    /usr/bin
    /usr/sbin
    /usr/lib
    /usr/local/   -- kolmas korrus
    /usr/share
  /var   -- log failid, web'i majutus, ..

special places
..............

  /    -- root directory, top of the file tree
  ..   -- one floor up
  .    -- 'this' folder
  ~    -- home folder
  -    -- previous folder

Examples

  $ cd / ; pwd ; ls -1 | head -n 3
  /
  bin
  boot
  cdrom
  $ cd -
  /
  $ cd ~ ; pwd
  /home/virtu
  $ cd / ; pwd; ls -1 | head -n 3
  /
  bin
  boot
  cdrom
  $ cd -
  /home/virtu
  $ cd .. ; pwd
  /home
  $ cd virtu ; pwd
  /home/virtu
  $ cd /usr/share ; pwd; ls -l
  /usr/share
  $ cd /usr/share/applications ; pwd
  /usr/share/applications

FILE
....

  body:  cat, filters

  names: ls, ln, ln -s, touch, rm, mkdir, rmdir

  visibility: regular, hidden ( .filename, ls -a)

  type:

    -   -- regular file
    c   -- character device
    b   -- block device
    d   -- directory
    l   -- soft link

  access

    owner, group, other
    read, write, execute

    octal numbers: [0-7][0-7][0-7]
    access mask
      chmod mask filename
      chown user:group filename

  time and date

    $ dd if=/dev/zero count=123456 bs=1 of=example
    123456+0 records in
    123456+0 records out
    123456 bytes (123 kB, 121 KiB) copied, 0,169877 s, 727 kB/s
    $ ln example alien
    $ ln -s softlink bad
    $ ln example hardlink
    $ rm example
    $ ls -l alien

  accessmask             c* owner group length month day time  name
  type:owner:group:other
  -    rw-   r--   r--   2  virtu virtu 123456 dets  25  11:57 example

  *) where c is a number of hard linked names.
     soft link dies, when last hard name is deleted.

  special

    suid bit
    sgid bit
    sticky bit

  See annex E:

    https://www.thegeekdiary.com/what-is-suid-sgid-and-sticky-bit/

Example: Write file to a directory, but no list or delete.

  virtu@RBOX:~$ mkdir kt
  virtu@RBOX:~$ cd kt
  virtu@RBOX:~/kt$ mkdir weird
  virtu@RBOX:~/kt$ sudo chown root:root weird
  virtu@RBOX:~/kt$ sudo chmod 1733 weird
  virtu@RBOX:~/kt$ touch weird/a
  virtu@RBOX:~/kt$ touch weird/aa
  virtu@RBOX:~/kt$ ls -l weird
  ls: cannot open directory 'weird': Permission denied
  virtu@RBOX:~/kt$ sudo ls -l weird
  total 0
  -rw-r--r-- 1 virtu virtu 0 Dec 25 13:13 a
  -rw-r--r-- 1 virtu virtu 0 Dec 25 13:13 aa
  virtu@RBOX:~/kt$ sudo tree weird
  weird
  ├── a
  └── aa

  0 directories, 2 files
  virtu@RBOX:~/kt$ sudo ls -lR
  .:
  total 4
  drwx-wx-wt 2 root root 4096 Dec 25 13:13 weird

  ./weird:
  total 0
  -rw-r--r-- 1 virtu virtu 0 Dec 25 13:13 a
  -rw-r--r-- 1 virtu virtu 0 Dec 25 13:13 aa

Reference

  http://bitsavers.informatik.uni-stuttgart.de
  /pdf/att/unix/2nd_Edition/UNIX_Programmers_Manual_2ed_Jun72.pdf

Annex A. explaing wormhole
--------------------------

  PS G:\temp> cat m.c
  #include <stdio.h>
  #include <string.h>
  #define FOREACH(x,n) for((x)=0;(x)<=(n);(x)++)

  int main() {
    /* $ as {CAPS} */
    char* font[2] = {"ABCDEFGHIJKLMNOPQRSSZZTUVW628Y\\Y",
                     " !X" };
    int terex[] =
       {0x16,0x4,0x11,0x4,0x1e,0,0xc,0x0,0x0,0x8,0xb,0xc,0x1e,1};
    int idx,flr;
    printf("%d %d\n", strlen(font[0]), strlen(font[1]));
    FOREACH(flr,1) FOREACH(idx,strlen(font[flr])-1)
      putchar(font[flr][idx]);
    printf("\n"); flr = 0;
    FOREACH(idx,sizeof(terex)/4-1) {
      if (!flr) {
        flr=font[flr][terex[idx]]=='\\'?1:0;
        if (!flr) putchar(font[flr][terex[idx]]);
      }
      else
        putchar(font[flr--][terex[idx]]);
    }
    return 0;
  }
  PS G:\temp> .\m.exe
  32 3
  ABCDEFGHIJKLMNOPQRSSZZTUVW628Y\Y !X
  TERE MAAILM!

Annex B. aplusb.c, PHP style (1banana is a number)
--------------------------------------------------

  #include <stdio.h>
  #include <string.h>
  #include <stdlib.h>
  #define FOREACH(x,n) for((x)=0;(x)<=(n);(x)++)

  /* gcc aplusb.c -o aplusb */

  int iszero(char* a) {
    char*b = a;
    while(*a=='0')a++;
    printf("%x %x %d %d\n", a, b, a-b, strlen(b));
    if (a-b==0 || strlen(b)!=a-b) return 0;
    return 1;
  }

  int main(int argc, char** argv) {
    long  v[] = {1,2},t;
    int   i;
    char* end;
    FOREACH(i,argc-2) {
      t=strtol(argv[i+1],&end,10);
      if (iszero(argv[i+1])||t) v[i]=t;
      else if (!t)
        printf("%s not a number, default is used\n", argv[i+1]);
    }
    printf("%d+%d=%d\n",*v,*(v+1),*v+*(v+1));
    return 0;
  }

Annex C. Unattended Partitioning
--------------------------------

  #!/bin/bash
  if [ `id -u` -ne 0 ]
  then
    echo 'Have to be root'
    exit 1
  fi
  echo 'Power and chaos'
  dd if=/dev/zero of=/dev/sdb bs=512 count=63
  echo "n
  p
  1

  +2G
  t
  82
  w" | fdisk /dev/sdb
  sleep 1
  echo "n
  p
  2


  a
  2
  w" | fdisk /dev/sdb
  sleep 1
  fdisk -l /dev/sdb
  mkswap /dev/sdb1
  echo y | mkfs.ext4 /dev/sdb2

Annex D. 2+2=4
--------------

  https://www.codeproject.com/Questions/275223
  /Regular-expressions-using-regex-h

  #include <sys/types.h>
  #include <regex.h>
  #include <stdio.h>

  // The maximum number of matches allowed in a single string
  #define MAX_MATCHES 1

  void match(regex_t *pexp, char *sz) {
    // A list of the matches in the string (a list of 1)
    regmatch_t matches[MAX_MATCHES];
    // Compare the string to the expression
    // regexec() returns 0 on match, otherwise REG_NOMATCH
    if (regexec(pexp, sz, MAX_MATCHES, matches, 0) == 0) {
      printf("\"%s\" matches characters %d - %d\n", sz,
             matches[0].rm_so, matches[0].rm_eo);
    } else {
      printf("\"%s\" does not match\n", sz);
    }
  }

  int main() {
    int rv;
    regex_t exp; // Our compiled expression
    // 1. Compile our expression.
    // Our regex is "-?[0-9]+(\\.[0-9]+)?". I will explain this later.
    // REG_EXTENDED is so that we can use Extended regular expressions
    rv = regcomp(&exp, "-?[0-9]+(\\.[0-9]+)?", REG_EXTENDED);
    if (rv != 0) {
      printf("regcomp failed with %d\n", rv);
    }
    // 2. Now run some tests on it
    match(&exp, "0");
    match(&exp, "0.");
    match(&exp, "0.0");
    match(&exp, "10.1");
    match(&exp, "-10.1");
    match(&exp, "a");
    match(&exp, "a.1");
    match(&exp, "0.a");
    match(&exp, "0.1a");
    match(&exp, "hello");
    // 3. Free it
    regfree(&exp);
    return 0;
  }

Now for a basic explanation of regular expressions.

The original regular expressions were pretty basic. They included:

  One of         [AB]    one of A or B
  Not one of     [^AB]   anything but A and B
                         (new line may or may not be included,
                          implementation or option specific)
  Zero or more   A*      any number of A's including 0
  Group          (A)     Used for grouping things like OR
  Any character  .       Any single character (not including new line)

Then came extended regular expressions, which added many useful features:

  Zero or one    A?      Either zero or 1 A
                         (same as "A\{0,1\}" in basic regex)
  Or             A|B     Either A or B
  One or more    A+      One or more A's
                         (same as "AA*" in basic regex)

Then there are predefined lists of characters, as a shorthand of writing [ABC], see Wikipedia[^] for a full list. These can be implementation specific, however the GNU one supports all sets listed at Wikipedia.

The easiest way to build a regular expression is to break it down into its simplest parts, and them combine them together.

For example we want an expression that will find any words starting with A and ending with B OR starting with B and ending with A.

First, break it into its 2 components

  1. A.*B
  2. B.*A

Now group them together with an OR

  (A.*B)|(B.*A)

Note that this is different to [AB].*[AB], which will also match AA, AxA, BB, ...

Annex E. What is SUID, SGID and Sticky bit?
-------------------------------------------

By Sandeep

  https://www.thegeekdiary.com/what-is-suid-sgid-and-sticky-bit/

There are 3 special permission that are available for executable files and directories. These are :

  1. SUID permission
  2. SGID permission
  3. Sticky bit

### Set-user Identification (SUID) ###

Have you ever thought, how a non-root user can change his own password when he does not have write permission to the /etc/shadow file. hmmm.. interesting isn't it? Well to understand the trick check for the permission of /usr/bin/passwd command :

  # ls -lrt /usr/bin/passwd
  -r-sr-sr-x   1 root     sys        31396 Jan 20  2014 /usr/bin/passwd

  – If you check carefully, you would find the 2 S's in the permission field. The first s stands for the SUID and the second one stands for SGID.

  – When a command or script with SUID bit set is run, its effective UID becomes that of the owner of the file, rather than of the user who is running it.

  – Another good example of SUID is the su command:

  # ls -l /bin/su
  -rwsr-xr-x-x 1 root user  16384 Jan 12 2014 /bin/su

  – The setuid permission displayed as an "s" in the owner's execute field.

How to set SUID on a file?

  # chmod 4555 [path_to_file]

Note: If a capital "S" appears in the owner's execute field, it indicates that the setuid bit is on, and the execute bit "x" for the owner of the file is off or denied.

### Set-group identification (SGID) ###

SGID permission on executable file

  – SGID permission is similar to the SUID permission, only difference is – when the script or command with SGID on is run, it runs as if it were a member of the same group in which the file is a member.

  # ls -l /usr/bin/write
  -r-xr-sr-x  1   root tty 11484 Jan 15 17:55 /usr/bin/write

  – The setgid permission displays as an “s” in the group's execute field.

Note: If a lowercase letter "l" appears in the group's execute field, it indicates that the setgid bit is on, and the execute bit for the group is off or denied.

How to set GUID on a file?

  # chmod 2555 [path_to_file]

## SGID on a directory ##

  – When SGID permission is set on a directory, files created in the directory belong to the group of which the directory is a member.

  – For example if a user having write permission in the directory creates a file there, that file is a member of the same group as the directory and not the user's group.

  – This is very useful in creating shared directories.

How to set SGID on a directory

  # chmod g+s [path_to_directory]

### Sticky Bit ###

  – The sticky bit is primarily used on shared directories.

  – It is useful for shared directories such as /var/tmp and /tmp because users can create files, read and execute files owned by other users, but are not allowed to remove files owned by other users.

  – For example if user bob creates a file named /tmp/bob, other user tom can not delete this file even when the /tmp directory has permission of 777. If sticky bit is not set then tom can delete /tmp/bob, as the /tmp/bob file inherits the parent directory permissions.

  – root user (Off course!) and owner of the files can remove their own files.

Example of sticky bit :

  # ls -ld /var/tmp
  drwxrwxrwt  2   sys   sys   512   Jan 26 11:02  /var/tmp

  - T refers to when the execute permissions are off.
  - t refers to when the execute permissions are on.

How to set sticky bit permission?

  # chmod +t [path_to_directory]

or

  # chmod 1777 [path_to_directory]

When applying permissions to directories on Linux, the permission bits have different meanings than on regular files.

  https://unix.stackexchange.com/questions/21251
  /execute-vs-read-bit-how-do-directory-permissions-in-linux-work

  - The write bit allows the affected user to create, rename, or delete files within the directory, and modify the directory's attributes

  - The read bit allows the affected user to list the files within the directory

  - The execute bit allows the affected user to enter the directory, and access files and directories inside

  - The sticky bit states that files and directories within that directory may only be deleted or renamed by their owner (or root)

