CPS 346 & 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 which 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 $ export PERSON)

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

  • 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 know 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 alias
  • other features are tailored through environment variables


Command-line tips

  • 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 which 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
    • : at beginning or end
    • :: 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 pkg_add
      
  • 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 which execute at log in, and which need execute only once
  • sample .profile:

      CDPATH=.:..:$HOME
      PATH=.:./bin:$HOME/bin:/bin:/sbin:/usr/bin:/usr/sbin:/usr/ucb:\
      /usr/local/bin:/usr/bin/X11 
      EDITOR=/usr/ucb/vi
      ENV=$HOME/.kshrc
      EXINIT='set ai nonumber showmatch wrapmargin=72 nowrapscan'
      FCEDIT=/usr/ucb/vi
      HISTSIZE=32
      MAIL=/usr/spool/mail/$USER
      HOST=$(hostname)
      PS1="! ${HOST%%.*}> "
      SHELL=/usr/bin/ksh
      export CDPATH EDITOR ENV EXINIT FCEDIT HISTSIZE HOST MAIL PATH PS1
      export SHELL
      biff y
      tset -I
      stty  erase \^? kill \^U intr \^C
      umask 0077
      alias mail=/usr/ucb/mailx
      OSTYPE=`uname`
      

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

      CDPATH: directories searched by cd command

      PS1: primary prompt string; default is $

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

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

      EXINIT: sets 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

      biff y: system notifies user of new mail

      stty erase: sets delete character for command line edits

      umask: sets (eliminates) file default access permissions

      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
      
      locate commands as they are defined

  • history mechanism
    • for saving recently executed commands (events)
    • 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


.profile vs. (value of) ENV variable

  • .profile run at login for Bourne, Korn, and Bash shells, but not for C shell (.login used)
  • 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 it is advisable to put them in)


.plan and .project

finger <logname>
  • finger cps444-n1.01
  • add .plan and .project to your home directory


Configuring vi

  • EXINIT variable
  • set showmode showmatch ruler
  • syntax on
  • .exrc (resource configuration) file
  • vim's analog of .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