CPS 356 & 444/544 Lecture notes: Process Environment



Coverage: [UPE] Chapters 1 (pp. 31-33), 3 (pp. 88-92), and 6 (pp. 199-200), and [USP] Chapter 2 (pp. 48-51)


Variables

  • a shell variable can have any name of the form [A-Za-z][A-Za-z0-9_]* (akin to a C identifier)

  • to define in ksh: <variable>=<value>; spaces not permitted on either side of the equal sign (e.g., $ person=Linus)

  • to retrieve the value, precede the variable name with a dollar sign ($):
       $ echo person
       person
       $ echo $person
       Terry
    
  • unsetting (erasing) variables:
       $ unset person
    
    this is not the same as person='', which leaves the variable defined, but with the null value

  • variables and quotes
    • quotes are used to specify values that contain spaces or metacharacters
    • double quotes (") prevent shell interpretation of metacharacters except $, \, " ", or $(<command>) (equivalent to depracated method of command substitution using grave quote `<command>`)
    • single quotes (') prevent shell interpretation of all metacharacters
    • backslash (\) prevents the shell from interpreting the next character specially
    • examples:
      $ people="jack and jill *"
      $ print "$people"
      jack and jill *
      $ print $people
      jack and jill file1 file2 file3
      $ print '$people'
      $people
      $ print \$people
      $people
      
  • set (shell builtin): displays all variables (name, value) pairs

  • env (UNIX command): shows only environment variables (i.e., those which are exported)
    • why doesn't env X=10 echo $X work as expected?
    • env X=10 env

  • ksh < ourscript and ksh ourscript
    • do each of these commands create a new (child) shell process?
    • will variables created in ourscript be visible to current shell?

  • purpose of . (source, a shell builtin): source its file argument in the current shell process (not a child shell process) (e.g., . ./ourscript or . .profile)


Environments

  • `an environment list consists of an array of pointers to strings of the form name = value' [USP] (p. 48)
  • `the name specifies an environment variable, and the value specifies a string value associated with [that] variable' [USP] (p. 48)
  • environment variables are a subset of all variables known to the current shell
  • `environment variables provide a mechanism for using system-specific or user-specific information in setting defaults within a program' [USP] (p. 49) (e.g., a program may need to write a file to the user's home directory)

  • define using export <variable>=<value> (export is a shell builtin); makes the variable visible to all descendant processes (or an environment variable) (e.g., $ export PERSON=Linus or $ PERSON=Linus; export PERSON)

  • can a descendant shell pass variables up to an ancestor or is it just one-way from ancestor to descendants? explain.

  • accessing the environment
    • extern char** environ variable points to the process environment list when the process starts execution; strings may appear in any order
    • use char* getenv (const char* name) (prototyped in stdlib.h) `to determine whether a specific variable has a value in the process environment' [USP] (p. 49)
      • returns NULL if variable does not have a value
      • otherwise, returns a pointer to the string containing the value
      • `be careful about calling getenv more than once without copying the first return string into a buffer; some implementations of getenv use a static buffer for the return strings and overwrite the buffer on each call' [USP] (p. 49)
    • see [UPE] §6.9 (p. 199)

  • ref. [USP] example 2.2 (p. 49)
    /* outputs the contents of its environment list */
    #include<stdio.h>
    
    extern char** environ;
    
    int main (void) {
       int i;
    
       if (environ != NULL) {
          printf ("The environment list follows:\n");
          for (i=0; environ[i] != NULL; i++)
             printf ("environ[%d]: %s\n", i, environ[i]);
       } else
            printf ("The environment is empty.\n");
       return 0;
    }
    
  • ref. [USP] example 2.23 (p. 50) with minor modifications
    #include<stdio.h>
    #include<stdlib.h>
    #define MAILDEFAULT "/var/mail"
    
    /* POSIX standard specifies that shell should use MAIL if MAILPATH not set */
    main() {
       char* mailp = NULL;
    
       if ((mailp = getenv ("MAILPATH")) == NULL)
          if ((mailp = getenv ("MAIL")) == NULL)
             mailp = MAILDEFAULT;
    }
    
  • do not confuse environment variables with predefined constants like NULL (in stdio.h) or MAX_CANON; while both use upper-case convention, constants are known at compile time, and environment variables are dynamic and not known until run time


New account environment

  • new accounts are tailored with some basic settings to make interaction easier
  • many shortcuts have been setup to work through aliases
  • enter alias (a shell builtin) to see all aliases
  • commands with arguments can be aliased (e.g., alias ls="ls -F")
  • unalias ls removes the ls alias
  • other features are tailored through environment variables


Command-line editing

  • normally, command line is in vi insert mode, <delete> key deletes previous character

  • <esc> switches to vi "command mode"

  • use h/l keys to move left/right in line (command mode)

  • x/X deletes character under/before cursor

  • to insert/append text, type i/a <text> <esc>

  • to recall previous commands for editing/re-execution, use <esc>, then k/j keys

  • default command prompt includes machine name and current working directory name for reference

  • as we learn about vi, many of its editing functions will also work on the command line (some to try: w, W, b, B, e, E, dw, de, D, 0, A, etc)

  • hitting <esc>\ will cause the shell to try to complete the file or program name you are currently typing

  • hitting <esc>= will instead list all possible completions that are available at the current cursor position

  • hitting <esc>* will insert all possible file name completions on the command line


PATH variable

  • a colon delimited list of absolute paths
  • searched from left to right
  • advisable to omit current working directory from the PATH, why?
  • how to include current working directory
    • .: or : at beginning
    • :. or : at end
    • :.: or :: in middle
  • which <command(s)>
    • locate a program file in the user's path
    • searches the user's command path (from left to right) for the given command(s), indicating which directory (if any) it is found in (e.g., which ls)
    • how can you find a command on the system so then you can add the found directory to your path? will the which command do it?
  • which is not to be confused with whereis or type (a shell builtin)
    • syntax: whereis <command(s)>
    • searches for the given command in common places; in some versions, will also uncover manual pages or source files
    • examples:
      $ whereis more
      $ whereis less
      
  • modified version of solution to [USP] exercise 2.24 (p. 51)
    #include <stdio.h>
    #include <stdlib.h>
    #define PATH_DELIMITERS ":"
    
    int tokenizepath (const char* s, const char* delimiters, char*** argvp);
    
    main (void) {
    
       char** tokenized_path = NULL;
       char* path = getenv ("PATH");
    
       if (tokenizepath (path, PATH_DELIMITERS, &tokenized_path) != -1)
          while (*tokenized_path != NULL)
            printf ("%s\n", *tokenized_path++);
    }
    
  • CDPATH and MANPATH work similarly


Korn shell configuration and customization

  • environment startup file .profile contains commands that execute at log in, and that need execute only once
  • sample .profile:

      export PATH=/bin:/usr/bin:/usr/local/bin:/usr/X11R6/bin
      PATH=$PATH:/sbin:/usr/sbin:/usr/games
      
      HOST=$( echo $(hostname) | awk -F. '{print $1}' )
      
      # for use with the Bash shell
      PS1='[$USER@$HOST:$(pwd)]\n$ '
      #PS1='[$USER@$HOST:$PWD] $ '
      #PS1='[! $USER@$HOST:$PWD]\\n$ '
      
      # for use with the Korn shell
      #PS1='[! $USER@$HOST:$PWD]
      #$ '
      
      export MANPATH=/usr/share/man:/usr/local/man
      
      # Setting TERM is normally done through /etc/ttys.  Do only override
      # if you're sure that you'll never log in via telnet or xterm or a
      # serial line.
      # Use cons25l1 for iso-* fonts
      # TERM=cons25;  export TERM
      #export TERM=vt100
      export TERM=xterm-color
      
      BLOCKSIZE=K;    export BLOCKSIZE
      HISTORY=32;     export HISTORY
      PAGER=less;     export PAGER
      MANPAGER=less;  export MANPAGER
      VISUAL=vi;      export VISUAL
      EDITOR=vi;      export EDITOR
      FCEDIT=vi;      export FCEDIT
      CVSEDITOR=vi; export CVSEDITOR
      EXINIT="set ruler showmode showmatch"; export EXINIT
      
      # set ENV to a file invoked each time sh is started for interactive use.
      ENV=$HOME/.bashrc; export ENV
      #ENV=$HOME/.kshrc; export ENV
      
      umask 0007
      

      PATH: directories searched for any file (command) name; an important shell variable

      CDPATH: directories searched by cd command

      PS1: primary prompt string; default is $

      PS2: secondary prompt string that defines prompt for continued lines; default is >; commonly used in shell programming

      ENV: name of script that is executed when a new instance of the shell is instigated

      EXINIT: sets initial options for ex and vi editors

      FCEDIT: editor used by the fc command

      EDITOR: sets default editor

      HISTSIZE: number of history commands available (must be set before ksh is started)

      SHELL: name of shell environment

      export: pass the value of shell variables, making them accessible to descendant processes

      tset: initializes terminals, setting the TERM variable

      stty erase: sets delete character for command line edits

      umask: sets default file access permissions

      biff y: system notifies user of new mail

      alias: allows commands (and options) to be abbreviated

  • .kshrc file: contains shell commands executed whenever a new Korn shell is instigated, if .kshrc is the value of the ENV variable

  • sample .kshrc file:
    • set -o  trackall
      set -o vi
      #set -o noclobber
      
      # -x is deprecated and has no effect
      alias -x more="less"
      unalias ls
      alias -x ls="ls --color=auto -F"
      alias -x ll="ls -l"
      alias -x l="ls -l"
      alias -x vi="vim"
      #alias -x print1="enscript -d LaserJetP4015"
      
      . $HOME/.profile
      
      locate commands as they are defined

  • history mechanism
    • for saving recently executed commands
    • export HISTSIZE=25 (save the last 25 commands)
    • enter history (a shell builtin) to dislay your history list of commands
    • enter r <n> to re-execute command with number <n> (e.g., r 3 (executes command number 3 in the history list))
    • r - re-executes the last executed command
    • r prog re-executes the most recent command beginning with the string prog

  • changing shells (chsh)


.profile vs. (value of) ENV variable

  • .profile run at login for Bourne, Korn, and Bash shells, but not for C shell (.login used instead)
  • ENV=".kshrc"; variable whose value should be set to a filename; this filename is sourced when a new instance of the shell is instigated
  • how can we prevent "Good Day!" from appearing twice on login?
  • aliases (in which configuration dot file it is advisable to put them in?)


.plan and .project

finger <logname>
  • finger FA_14_CPS356_07
  • add .plan and .project to your home directory


Configuring vi

  • EXINIT variable
  • e.g., export EXINIT="set ruler showmode showmatch"
  • .exrc (resource configuration) file
  • vim's analog of vi's .exrc is .vimrc


References

    [UPE] B.W. Kernighan and R. Pike. The UNIX Programming Environment. Prentice Hall, Upper Saddle River, NJ, Second edition, 1984.
    [USP] K.A. Robbins and S. Robbins. UNIX Systems Programming: Concurrency, Communication, and Threads. Prentice Hall, Upper Saddle River, NJ, Second edition, 2003.

Return Home