SMU School of Engineering
General Use UNIX Machines

 

SEAS-Net Frequently Asked Questions

Contents:

  1. Intro
  2. Reading the online documentation
  3. How do I make my backspace key work?
  4. What printers are available and how do I print to them?
  5. How do I find out how much paper quota I have left to print?
  6. How do I find out how much disk space I am using?
  7. Where do I report problems with equipment?
  8. How can I dial into SEAS-Net from home?
  9. What type of modem file transfer protocols does SEAS-Net have?
  10. How do I use ``kermit'' to transfer a file?
  11. How do I remove a file whose name begins with a - ?
  12. How do I get a recursive directory listing?
  13. How do I get the current directory into my prompt?
  14. How do I read characters from a terminal without requiring the user to hit RETURN?
  15. How do I read characters from the terminal in a shell script?
  16. How do I check to see if there are characters to be read without actually reading?
  17. How do I rename *.foo to *.bar, or change file names to lowercase?
  18. Why do I get [some strange error message] when I `rsh host command'?
  19. How do I find out the creation time of a file?
  20. How do I use rsh without having the rsh hang around until the remote command has completed?
  21. How do I truncate a file?
  22. How do I {set an environment variable, change directory} inside a program or shell script and have that change affect my current shell?
  23. Why doesn't find's {} symbol do what I want?
  24. How do I redirect stdout and stderr separately in csh?
  25. How do I set the permissions on a symbolic link?
  26. When someone refers to 'rn(1)' or 'ctime(3)', what does the number in parentheses mean?
  27. What does {awk,grep,fgrep,egrep,biff,cat,gecos,nroff,troff,tee,bss,rc} stand for?
  28. How do I ``undelete'' a file?
  29. How can a process detect if it's running in the background?
  30. How can an executing program determine its own pathname?
  31. How do I tell inside .cshrc if I'm a login shell?
  32. How do I use popen(3) to open a process for reading AND writing?
  33. How do I run 'passwd', 'ftp', 'telnet', 'tip' and other interactive programs from a shell script or in the background?
  34. How do I sleep() in a C program for less than one second?
  35. What's wrong with having '.' in your $PATH ?
  36. Is it possible to reconnect a process to a terminal after it has been disconnected, e.g. after starting a program in the background and logging out

  1. Intro

  2. While the system appears to be confusing, vertually everything is documented, so mewhere. the trick is quickly locating the relevent information. This document attempts to give you some guide lines on how to go about getting help about a perticular subject matter. Basically there are four ways of getting help on an aspect of the system:

    • Reading the manual page(s).
    • Reading the Frequently asked questions documentation.
    • Asking a lab manager or instructor.
    • Sending email to 'help@seas.smu.edu'.
    • Calling the SEAS Help Desk at 768-7327 (311-A Caruth Hall)

  3. Reading the online documentation
  4. The absolute best way to obtain factual information about a command is by Reading its online manual page(s). Some day you may encounter the phrase 'RTFM', which stands for 'Read the Fine Manual' (except 'F' doesn't really stand for "Fine"). If you ask someone a question and they tell you to RTFM, it's an indication that you haven't done enough research. For instance, if you are having trouble removing a file whose name begins with a "-", check the man page for rm. It might tell you what you need to know. When people use terminology like 'read(2), they are referring to the 'read' man page in section 2 of the manual (which you would see by using 'man 2 read').

    There are a couple of commands that will help you in your quest for the right "manual" page.

    • apropos
      The apropos command shows which manual sections contain instances of any of the given keywords in their title. Each word is considered separately and the case of letters is ignored. Words that are part of other words are listed. Thus, looking for the word compile hits all instances of `compiler' also. If the line starts `name(section) ...' you can do `man section name' to get the documentation for it.

      For example, the following command line lists all commands that have to do with formatting:

        apropos format
      To then access the reference page for the printf subroutine that you see listed, type:

        man 3s printf
    • whatis
    • The whatis command looks up a given command and gives the header line from the manual section. You can then run the man(1) command to get more information. If the line starts ``name(section) ...'' you can do ``man section name'' to get the documentation for it. Try:

      whatis ed

      and then you should do:

        man 1 ed

      to get the manual page.
       
       
    • man
      The basic function of this command is to provide online displays of reference pages. You can use options, however, to direct the man command to display one line summaries of reference pages which contain specific keywords, to display one line summaries of specific reference pages, to use special formatting options when preparing the reference page for display or printing, and to search alternate reference page directories for specified reference pages.

      If an option is not used, the man command formats and displays one or more specified reference pages. If there are multiple reference pages which match a specified name, only the first matching reference page is displayed. If there are multiple matches in a section for a specified name, the matching page in the first alphabetically occurring subsection is displayed.

      If you specify the man command with a section argument, the man command looks in that section of the reference pages for the specified page titles. A section consists of a number in the range 0 to 9, optionally followed by an alphanumeric subsection.

      If a section is omitted, the man command searches all sections of the reference pages. The man command displays commands (both standard and local) over subroutines in system libraries, and displays the first occurrence it finds, if any.

      As an example, to get information on the cc (c compiler) command you would type the command:

        man cc

  5. How do I make my backspace key work?
  6. There are currently two well known backspace keys, a ASCII 8 or Control-H and a Delete. Murphys law says that whatever you are logging into will undoubtably use the other one from the terminal you have. The easiest way to resolve the problem is to type the command:

      stty erase BS-key RETURN

    Where BS-key is the key on the keyboard that would normally be your backspace. Note: YOU DO NOT WANT TO USE AN ARROW KEYas your backspace key. Arrow keys are meant for cursor movement inside of applications not for text handling on the command line.

  7. What printers are available and how do I print to them?
  8. Currently there are several printers available; below is a list of the printer and the type of file expected to be printed on it.

    Printer Name Type Location Data Expected
    sic_lp Line SIC Public Termina Area Program listings, text, etc.
    sic_si Laser SIC Public Terminal Area Postscript
    clem15 Line Clements Hall Basement Program listings, text, etc.
    ch_lp Line Caruth Public Terminal Area Program listings, text, etc.
    ch_si Laser Caruth Public Terminal Area Postscript
    ch_215 Line Room 215 Caruth Program listings, text, etc.
    me_lab Laser CME lab1 Terminal Area Postscript

    Accessing a printer is done usually via the -P option of lpr(1). To print a program listing on the printer in Clements Lab for example:

      lpr -Pclem15 listing.c

  9. How do I find out how much paper quota I have left to print?
  10. The command pquota(1) will give you a summarized listing of how many paper units you have left to print. See the manual page for paper_policy(1) for information on how this is calculated.

  11. How do I find out how much disk space I am using?

    The command du(1) will answer this. From your home directory type the command:

      du -s

    This will return the number of 1024 byte blocks your account is consuming. Compression of older data or programs is highly recommended. See the man pages for gzip(1) and gunzip(1) for more information.

    Also, if you are subject to disk quotas, the dquota(1) command will return the amount of disk quota you've been assigned and the current amount you are using.

  12. Where do I report problems with equipment?

    Generally you report problems to your TA or instructor. If there really appears to be a serious problem of some kind sending email to help@seas.smu.edu will generally get someones attention.

  13. How can I dial into SEAS-Net from home?
    Currently there is one primary dial in rotary. The number is (214)-768-1710. This number will support modems from 1200 baud to 19200 baud using 8 bits, no parity, and 1 stop bit.


  14. What type of modem file transfer protocols does SEAS-Net have?

    We have several, what you can use from home may be a different question. Basically we recommend using kermit(1). It's simple enough to live thru whatever connection you established to get here. It's possible to use the rz/sz Xmodem programs but sometimes they don't work for whatever reason. As it is we continually monitor kermits functionallity. If you suspect a problem on this send send email about it to 'help@seas.smu.edu'. If they tell you kermit's working, the problem is more than likely on your end.

  15. How do I use ``kermit'' to transfer a file?

    After you have logged into the SEAS network, you can invoke kermit by typing kermit. If you are transfering a binary file, type 'set file type binary' at the CKermit> prompt which you will see after kermit starts up. If, on the otherhand, you are transfering a text file, type 'set file type text' after kermit starts up. To be safe, you should set the same file type in the communications package you are using on your PC. You will need to check the documentation for your communications package to determine how to to set the kermit file transfer type.

    After that, type 'send your_file_name' at the kermit prompt to send a file from the SEAS machine to your PC. If you are sending a file from your PC to one of the SEAS machines, you type 'receive file_name'. Kermit will tell you to escape back to your local system and give the receive command. Kermit will time out after a short time so you need to be ready to take the appropriate action on your side promptly.

    The escape command is different for each communications program. You will need to check the documentation for your communications program to determine the corect response. After the transfer is started, things should proceed until your file has been transferred.

  16. How do I remove a file whose name begins with a - ?

    Figure out some way to name the file so that it doesn't begin with a dash. The simplest answer is to use:
      rm ./-filename

    (assuming '-filename' is in the current directory, of course.) This method of avoiding the interpretation of the "-" works with other commands too.

    Many commands, particularly those that have been written to use the getopt(3) argument parsing routine, accept a "--" argument which means "this is the last option, anything after this is not an option", so your version of rm might handle '>rm -- -filename'. Some versions of rm that don't use getopt() treat a single "-" in the same way, so you can also try 'rm - -filename'.

  17. How do I get a recursive directory listing?

    One of the following may do what you want:

    • ls -R (not all versions of ls accept '-R')
    • >find . -print (should work everywhere)
    • du -a . (shows you both the name and size)

    If you're looking for a wildcard pattern that will match all '.c' files in this directory and below, you won't find one, but you can use:

      find . -name '*.c' -print

    find is a powerful program. Learn about it.

  18. How do I get the current directory into my prompt?

    It depends which shell you are using. It's easy with some shells, hard or impossible with others.

    C Shell (csh):

    Put this in your .cshrc - customize the prompt variable the way you want.

    alias setprompt 'set prompt="${cwd}% "'

    setprompt # to set the initial prompt

    alias cd 'chdir \\!* && setprompt'

    # if you need pushd and popd

    alias pushd 'pushd \\!* && setprompt'

    alias popd 'popd \\!* && setprom

    Bourne Shell (sh):

    If your machine has a newer version of the Bourne Shell (SVR2 or newer) you can use a shell function to make your own command, 'xcd' say:
    xcd() { cd $* ; PS1="`pwd` $ "; }
    Korn Shell (ksh):
    Put this in your .profile file:
    PS1='$PWD $ '
    If you just want the last component of the directory, use:
    PS1='${PWD##*/} $ '

    T C shell (tcsh):

    Tcsh is a popular enhanced version of csh with some extra builtin variables (and many other features):
     
                  

    %~ the current directory, using ~ for $HOME

    %d or %/ the full pathname of the current directory

    %c or %. the trailing component of the current directory

    so you can do: set prompt='%~ '

    BASH:

    \w in $PS1 gives the full pathname of the current directory, with ~ expansion for $HOME; \W gives the basename of the current directory. So, in addition to the above sh and ksh solutions, you could use:

      PS1='\w $ ' or PS1='\W $ '

  19. How do I read characters from a terminal without requiring the user to hit RETURN?

    If you don't want to tackle setting the terminal parameters yourself (using the ioctl(2) system call) you can let the stty program do the work - but this is slow and inefficient, and you should change the code to do it right some time, (see the CBREAK mode in the ioctl(2) manual page):
    #include main() { int c; printf("Hit any character to continue\\n"); /* * ioctl() would be better here; only lazy * programmers do it this way: */ system("/bin/stty cbreak"); /* or "stty raw" */ c = getchar(); system("/bin/stty -cbreak"); printf("Thank you for typing %c.\\n", c); exit(0); }

    You might like to check out the documentation for the curses library of portable screen functions. Often if you're interested in single-character input/output like this, you're also interested in doing some sort of screen display control, and the curses library provides various portable routines for both functions.

  20. How do I read characters from the terminal in a shell script?

    In sh, use read. It is most common to use a loop like:
    while read line do ... done

    In csh, use "$<" like this:

    while ( 1 ) set line = "$<" if ( "$line" == "" ) break ... end

    Unfortunately csh has no way of distinguishing between a blank line and an end-of-file.

  21. How do I check to see if there are characters to be read without actually reading?

    Certain versions of UNIX provide ways to check whether characters are currently available to be read from a file descriptor. In BSD, you can use select(2). You can also use the FIONREAD ioctl (see tty(4)), which returns the number of characters waiting to be read, but only works on terminals, pipes and sockets. In System V Release 3, you can use poll(2), but that only works on streams. In Xenix - and therefore Unix SysV r3.2 and later - the rdchk() system call reports whether a read() call on a given file descriptor will block.

    There is no way to check whether characters are available to be read from a FILE pointer. (You could poke around inside stdio data structures to see if the input buffer is nonempty, but that wouldn't work since you'd have no way of knowing what will happen the next time you try to fill the buffer.)

    Sometimes people ask this question with the intention of writing:

    if (characters available from fd) read(fd, buf, sizeof buf);
    in order to get the effect of a nonblocking read. This is not the best way to do this, because it is possible that characters will be available when you test for availability, but will no longer be available when you call read. Instead, set the ,strong>O_NDELAY oflag (which is also called FNDELAY under BSD) using the F_SETFL option of fcntl(2).

  22. How do I rename *.foo to *.bar, or change file names to lowercase?

    Why doesn't 'mv *.foo *.bar' work? Think about how the shell expands wildcards. "*.foo" and "*.bar" are expanded before the mv command ever sees the arguments. Depending on your shell, this can fail in a couple of ways. CSH prints "No match." because it can't match "*.bar". SH executes "mv a.foo b.foo c.foo *.bar", which will only succeed if you happen to have a single directory named "*.bar", which is very unlikely and almost certainly not what you had in mind.

    Depending on your shell, you can do it with a loop to mv each file individually. If your system has basename, you can use:

    • csh:

      foreach f ( *.foo ) set base=`basename $f .foo` mv $f $base.bar end

    • sh:
      for f in *.foo; do
         base=`basename $f .foo`
         mv $f $base.bar
      done

      If you don't have basename or want to do something like renaming foo.* to bar.*, you can use something like sed to strip apart the original file name in other ways, but the general looping idea is the same. You can also convert file names into mv commands with sed, and hand the commands off to sh for execution. Try:

        ls -d *.foo | sed -e 's/.*/mv & &/' -e 's/foo$/bar/' | sh

      Shell loops like the above can also be used to translate file names from upper to lower case or vice versa. You could use something like this to rename uppercase files to lowercase:

      • csh:
        foreach f ( * )
        mv $f `echo $f | tr '[A-Z]' '[a-z]'`
        end
      • sh:
        for f in *; do
        mv $f `echo $f | tr '[A-Z]' '[a-z]'`
        done

      • ksh:
        typeset -l l
        for f in *; do
        l="$f"
        mv $f $l
        done

  23. Why do I get [some strange error message] when I `rsh host command'?

    If your remote account uses the C shell, the remote host will fire up a C shell to execute 'command' for you, and that shell will read your remote .cshrc file. Perhaps your .cshrc contains a stty, biff or some other command that isn't appropriate for a non-interactive shell. The unexpected output or error message from these commands can screw up your rsh in odd ways.

    Fortunately, the fix is simple. There are, quite possibly, a whole *bunch* of operations in your .cshrc (e.g., 'set history=N') that are simply not worth doing except in interactive shells. What you do is surround them in your .cshrc with:

    if ( $?prompt ) then operations.... endif

    and, since in a non-interactive shell "prompt" won't be set, the operations in question will only be done in interactive shells.

    You may also wish to move some commands to your .login file; if those commands only need to be done when a login session starts up (checking for new mail, unread news and so on) it's better to have them in the .login file.

  24. How do I find out the creation time of a file?

    You can't - it isn't stored anywhere. Files have a last-modified time (shown by 'ls -l'), a last-accessed time (shown by 'ls -lu') and an inode change time (shown by 'ls -lc'). The latter is often referred to as the "creation time" - even in some man pages - but that's wrong; it's also set by such operations as mv, ln, chmod, chown and chgrp.

    The man page for stat(2) discusses this.

  25. How do I use rsh without having the rsh hang around until the remote command has completed?

    For instance, try doing rsh machine 'sleep 60 &' and you'll see that the rsh won't exit right away. It will wait 60 seconds until the remote sleep command finishes, even though that command was started in the background on the remote machine. So how do you get the 'rsh' to exit immediately after the 'sleep' is started?

    The solution - if you use csh on the remote machine:

      rsh machine -n 'command >&/dev/null </dev/null &'

    If you use sh on the remote machine:

      rsh machine -n 'command >/dev/null 2>&1 </dev/null &'

    Why? "-n" attaches rsh's stdin to /dev/null so you could run the complete rsh command in the background on the LOCAL machine. Thus "-n" is equivalent to another specific "< /dev/null". Furthermore, the input/output redirections on the REMOTE machine (inside the single quotes) ensure that rsh thinks the session can be terminated (there's no data flow any more.)

    Note: The file that you redirect to/from on the remote machine doesn't have to be /dev/null; any ordinary file will do. In many cases, various parts of these complicated commands aren't necessary.

  26. How do I truncate a file?

    The BSD function ftruncate() sets the length of a file. Xenix - and therefore SysV r3.2 and later - has the chsize() system call. For other systems, the only kind of truncation you can do is truncation to length zero with creat() or open(..., O_TRUNC).

  27. How do I {set an environment variable, change directory} inside a program or shell script and have that change affect my current shell?

    In general, you can't, at least not without making special arrangements. When a child process is created, it inherits a copy of its parent's variables (and current directory). The child can change these values all it wants but the changes won't affect the parent shell, since the child is changing a copy of the original data.

    Some special arrangements are possible. Your child process could write out the changed variables, if the parent was prepared to read the output and interpret it as commands to set its own variables.

    Also, shells can arrange to run other shell scripts in the context of the current shell, rather than in a child process, so that changes will affect the original shell.

  28. Why doesn't find's {} symbol do what I want?

    find has a -exec option that will execute a particular command on all the selected files. Find will replace any "{}" it sees with the name of the file currently under consideration.

    So, some day you might try to use find to run a command on every file, one directory at a time. You might try this:

      find /path -type d -exec command {}/\\* \\;

    hoping that find will execute, in turn:

       command directory1/*
       command directory2/*
       ...
    

    Unfortunately, find only expands the "{}" token when it appears by itself. Find will leave anything else like "{}/*" alone, so instead of doing what you want, it will do:

       command {}/*
       command {}/*
       ...
    

    once for each directory. This might be a bug, it might be a feature, but we're stuck with the current behaviour.

  29. How do I redirect stdout and stderr separately in csh?

    In csh, you can redirect stdout with ">", or stdout and stderr together with ">&" but there is no direct way to redirect stderr only. The best you can do is:

      ( command >stdout_file ) >&stderr_file

    which runs command in a subshell; stdout is redirected inside the subshell to stdout_file, and both stdout and stderr from the subshell are redirected to stderr_file, but by this point stdout has already been redirected so only stderr actually winds up in stderr_file.

  30. How do I set the permissions on a symbolic link?

    Permissions on a symbolic link don't really mean anything. The only permissions that count are the permissions on the file that the link points to.

  31. When someone refers to 'rn(1)' or 'ctime(3)', what does the number in parentheses mean?

    It looks like some sort of function call, but it isn't. These numbers refer to the section of the Unix manual where the appropriate documentation can be found. You could type 'man 3 ctime' to look up the manual page for ctime in section 3 of the manual.

  32. What does {awk,grep,fgrep,egrep,biff,cat,gecos,nroff,troff,tee,bss,rc} stand for?
awk
This language was named by its authors, Al Aho, Peter Weinberger and Brian Kernighan.

grep

Global Regular Expression Print

grep comes from the ed command to print all lines matching a certain pattern g/re/p where 're' is a regulat expression.

fgrep

Fixed GREP

fgrep searches for fixed strings only. The "f" does not stand for "fast" - in fact, "fgrep foobar *.c" is usually slower than "egrep foobar *.c" (Yes, this is kind of surprising. Try it.)

Fgrep still has its uses though, and may be useful when searching a file for a larger number of strings than egrep can handle.

egrep

Extended GREP, Egghead grep

egrep uses fancier regular expressions than grep. Many people use egrep all the time, since it has some more sophisticated internal algorithms than grep or fgrep, and is usually the fastest of the three programs.

cat

CATenate

catenate is an obscure word meaning "to connect in a series", which is what the "cat" command does to one or more files. Not to be confused with C/A/T, the Computer Aided Typesetter.

gecos

General Electric Comprehensive Operating System

When GE's large systems division was sold to Honeywell, Honeywell dropped the "E" from "GECOS".

Unix's password file has a pw_gecos field. The name is a real holdover from the early days. Dennis Ritchie has reported:

    "Sometimes we sent printer output or batch jobs to the GCOS machine. The gcos field in the password file was a place to stash the information for the $IDENT card. Not elegant."

nroff, troff, groff

New ROFF, Typesetter new ROFF, GNU's roff

These are descendants of "roff", which was a re-implementation of the Multics "runoff" program (a program that you'd use to "run off" a good copy of a document).

tee

T

From plumbing terminology for a T-shaped pipe splitter.

bss

Block Started by Symbol

Dennis Ritchie says:

    "Actually the acronym (in the sense we took it up; it may have other credible etymologies) is "Block Started by Symbol." It was a pseudo-op in FAP (Fortran Assembly [-er?] Program), an assembler for the IBM 704-709-7090-7094 machines. It defined its label and set aside space for a given number of words. There was another pseudo-op, BES, "Block Ended by Symbol" that did the same except that the label was defined by the last assigned word + 1. (On these machines Fortran arrays were stored backwards in storage and were 1-origin.)

    The usage is reasonably appropriate, because just as with standard Unix loaders, the space assigned didn't have to be punched literally into the object deck but was represented by a count somewhere."

biff

This command, which turns on asynchronous mail notification, was actually named after a dog at Berkeley.

We can confirm the origin of biff, if you're interested. Biff was Heidi Stettner's dog, back when Heidi (Eric Cooper, and Bill Joy) were all grad students at U.C. Berkeley and the early versions of BSD were being developed. Biff was popular among the residents of Evans Hall, and was known for barking at the mailman, hence the name of the command.

rc

rc (as in ".cshrc" or "/etc/rc") = "RunCom"

"rc" derives from "runcom", from the MIT CTSS system, ca. 1965.

There was a facility that would execute a bunch of commands stored in a file; it was called "runcom" for "run commands", and the file began to be called "a runcom."

"rc" is also the name of the shell from the new Plan 9 operating system.

  1. How do I ``undelete'' a file?
  2. Someday, you are going to accidentally type something like 'rm * .foo', and find you just deleted "*" instead of "*.foo". Consider it a rite of passage.

    For all intents and purposes, when you delete a file with "rm" it is gone. Once you "rm" a file, the system totally forgets which blocks scattered around the disk comprised your file. Even worse, the blocks from the file you just deleted are going to be the first ones taken and scribbled upon when the system needs more disk space. However, never say never. It is theoretically possible if you shut down the system immediately after the "rm" to recover portions of the data. However, you had better have a very wizardly type person at hand with hours or days to spare to get it all back.

    Your first reaction when you "rm" a file by mistake is why not make a shell alias or procedure which changes "rm" to move files into a trash bin rather than delete them? That way you can recover them if you make a mistake, and periodically clean out your trash bin. Two points: first, this is generally accepted as a bad idea. You will become dependent upon this behaviour of "rm", and you will find yourself someday on a normal system where "rm" is really "rm", and you will get yourself in trouble. Second, you will eventually find that the hassle of dealing with the disk space and time involved in maintaining the trash bin, it might be easier just to be a bit more careful with "rm". For starters, you should look up the "-i" option to "rm" in your manual.

  3. How can a process detect if it's running in the background?
  4. First of all: do you want to know if you're running in the background, or if you're running interactively? If you're deciding whether or not you should print prompts and the like, that's probably a better criterion.

    In general, you can't tell if you're running in the background. The fundamental problem is that different shells and different versions of UNIX have different notions of what "foreground" and "background" mean - and on the most common type of system with a better-defined notion of what they mean, programs can be moved arbitrarily between foreground and background!

    Shells that support job control, on UNIX systems that support job control, put a process into the background by giving it a process group ID different from the process group to which the terminal belongs. They move it back into the foreground by setting the terminal's process group ID to that of the process. Shells that do *not* support job control, on UNIX systems that support job control, typically do what shells do on systems that don't support job control.

  5. How can an executing program determine its own pathname?
  6. Your program can look at argv[0]; if it begins with a "/", it is probably the absolute pathname to your program, otherwise your program can look at every directory named in the environment variable PATH and try to find the first one that contains an executable file whose name matches your program's argv[0] (which by convention is the name of the file being executed). By concatenating that directory and the value of argv[0] you'd probably have the right name.

  7. How do I tell inside .cshrc if I'm a login shell?
  8. When people ask this, they usually mean either:
      How can I tell if it's an interactive shell? or
      How can I tell if it's a top-level shell?
    You could perhaps determine if your shell truly is a login shell (i.e. is going to source ".login" after it is done with ".cshrc") by fooling around with "ps" and "$$". Login shells generally have names that begin with a '-'. If you're really interested in the other two questions, here's one way you can organize your .cshrc to find out.
    if (! $?CSHLEVEL) then # # This is a "top-level" shell, # perhaps a login shell, perhaps a shell started up by # 'rsh machine some-command' # This is where we should set PATH and anything else we # want to apply to every one of our shells. # setenv CSHLEVEL 0 set home = ~username # just to be sure source ~/.env # environment stuff we always want else # # This shell is a child of one of our other shells so # we don't need to set all the environment variables again. # set tmp = $CSHLEVEL @ tmp++ setenv CSHLEVEL $tmp endif # Exit from .cshrc if not interactive, e.g. under rsh if (! $?prompt) exit # Here we could set the prompt or aliases that would be useful # for interactive shells only. source ~/.aliases
  9. How do I use popen(3) to open a process for reading AND writing?

    The problem with trying to pipe both input and output to an arbitrary slave process is that deadlock can occur, if both processes are waiting for not-yet-generated input at the same time. Deadlock can be avoided only by having BOTH sides follow a strict deadlock-free protocol, but since that requires cooperation from the processes it is inappropriate for a popen()-like library function.

    The 'expect' distribution includes a library of functions that a C programmer can call directly. One of the functions does the rather than pipes, and has no deadlock problem. It's portable to both BSD and SV. See the next answer for more about 'expect'.

    The shell itself cannot interact with interactive tty-based programs like these.

  10. How do I run 'passwd', 'ftp', 'telnet', 'tip' and other interactive programs from a shell script or in the background?

    The shell itself cannot interact with interactive tty-based programs like these.


  11. How do I sleep() in a C program for less than one second?

    The first thing you need to be aware of is that all you can specify is a MINIMUM amount of delay; the actual delay will depend on scheduling issues such as system load, and could be arbitrarily large if you're unlucky.

    If you aren't calling it in a tight loop, then you almost certainly aren't making microsecond-resolution requests anyway, in which case you don't care about microseconds. And if you did, you wouldn't be using UNIX anyway because random system indigestion (i.e., scheduling) can make mincemeat out of any timing code.

    The following code is adapted from Doug Gwyn's System V emulation support for 4BSD and exploits the 4BSD select() system call. Doug originally called it nap(); you probably want to call it usleep();

    /* usleep -- support routine for 4.2BSD system call emulations last edit: 29-Oct-1984 D A Gwyn */ extern int select(); int usleep( usec ) /* returns 0 if ok, else -1 */ long usec; /* delay in microseconds */ { static struct /* `timeval' */ { long tv_sec; /* seconds */ long tv_usec; /* microsecs */ } delay; /* _select() timeout */ delay.tv_sec = usec / 1000000L; delay.tv_usec = usec % 1000000L; return select( 0, (long *)0, (long *)0, (long *)0, &delay ); }

  12. What's wrong with having '.' in your $PATH ?
    A bit of background: the PATH environment variable is a list of directories separated by colons. When you type a command name without giving an explicit path (e.g. you type 'ls', rather than '/bin/ls') your shell searches each directory in the PATH list in order, looking for an executable file by that name, and the shell will run the first matching program it finds.

    One of the directories in the PATH list can be the current directory "." . It is also permissible to use an empty directory name in the PATH list to indicate the current directory. Both of these are equivalent.

    Consider what happens in the case where "." is the first entry in the PATH. Suppose your current directory is a publically-writable one, such as "/tmp". If there just happens to be a program named "/tmp/ls" left there by some other user, and you type "ls" (intending, of course, to run the normal "/bin/ls" program), your shell will instead run "./ls", the other user's program. Needless to say, the results of running an unknown program like this might surprise you.

    It's slightly better to have "." at the end of the PATH:

    Now if you're in /tmp and you type "ls", the shell will search /usr/ucb, /bin and /usr/bin for a program named "ls" before it gets around to looking in ".", and there is less risk of inadvertently running some other user's "ls" program. This isn't 100% secure though - if you're a clumsy typist and some day type "sl -l" instead of "ls -l", you run the risk of running "./sl", if there is one. Some "clever" programmer could anticipate common typing mistakes and leave programs by those names scattered throughout public directories. Beware.

    Many seasoned Unix users get by just fine without having "." in the PATH at all: If you do this, you'll need to type "./program" instead of "program" to run programs in the current directory, but the increase in security is probably worth it.

  13.   Is it possible to reconnect a process to a terminal after it has been disconnected, e.g. after starting a program in the background and logging out?

Most variants of Unix do not support detaching and attaching processes, as operating systems such as VMS and Multics support.