home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / unix / volume25 / finger / part07 / getttyloc.c next >
Encoding:
C/C++ Source or Header  |  1992-04-03  |  16.4 KB  |  601 lines

  1. /*
  2.  * getttyloc.c -- get tty location for finger (December 1985)
  3.  *
  4.  * Copyright (C) 1988, 1990  Philip L. Budne
  5.  *
  6.  * This file is part of "Phil's Finger Program".
  7.  *
  8.  * This program is free software; you can redistribute it and/or modify
  9.  * it under the terms of the GNU General Public License as published by
  10.  * the Free Software Foundation; either version 1, or (at your option)
  11.  * any later version.
  12.  *
  13.  */
  14.  
  15. # ifndef lint
  16. static char *rcsid = "$Id: getttyloc.c,v 3.0 90/07/06 13:10:53 budd Rel $";
  17. # endif /* lint not defined */
  18.  
  19. /*
  20.  *    This is pretty ad hoc and ugly.  To add a new flavor of
  21.  *    display you need to take care of two cases; With and without
  22.  *    user string (long and short displays)
  23.  *
  24.  *    TODO:
  25.  *
  26.  *    User ttylocs are stored per tty in a spool area.  Having the
  27.  *    user strings stored in a file containing an array of structs,
  28.  *    would save disk space.
  29.  *
  30.  *    Keeping ALL information (default short, long; current short,
  31.  *    long) in a central, binary file would save CPU in addition.
  32.  *    This way random programs (ie; supdup) could get the correct,
  33.  *    full ttyloc.
  34.  *
  35.  *    This could be done without tracking logins by date stamping
  36.  *    the user set and login dependant info (host, network, deamon)
  37.  *    The finger and ttyloc could update entries via set gid access.
  38.  *    (requies file and/or record locking?)
  39.  *
  40.  *    Use sprintf less!!
  41.  *
  42.  *    Could search cdevsw for ltaopen and ptcopen rather than using
  43.  *    LATPATH and PTYPATH
  44.  */
  45.  
  46. # ifndef X10_STR
  47. # define X10_STR "X10"            /* if no "screen" number */
  48. # endif /* X10_STR not defined */
  49.  
  50. # ifndef X11_STR
  51. # define X11_STR "X"            /* if have "screen" number */
  52. # endif /* X11_STR not defined */
  53.  
  54. # include <sys/types.h>
  55. # include <sys/stat.h>
  56. # include <strings.h>
  57. # include <ctype.h>
  58. # include <stdio.h>
  59. # include "finger.h"
  60. # include "person.h"
  61. # include "args.h"            /* before luser.h */
  62. # include "luser.h"
  63. # include "ttylocfile.h"
  64. # include "daemon.h"
  65. # include "pr.h"
  66.  
  67. # ifdef USG
  68. # include <sys/sysmacros.h>        /* for major() macro */
  69. # endif /* USG defined */
  70.  
  71. # ifdef ultrix
  72. # ifdef USE_DEVIOCGET
  73. # include <sys/file.h>
  74. # include <sys/ioctl.h>
  75. # include <sys/devio.h>
  76. # else  /* USE_DEVIOCGET not defined */
  77. LOCAL int latmajor = -1;
  78. # define LATPATH "/dev/tty15"
  79. # endif /* USE_DEVIOCGET not defined */
  80. # endif /* ultrix defined */
  81.  
  82. # ifndef DEFAULT_DAEMON
  83. # define DEFAULT_DAEMON "Virtual Terminal" /* NVT (host but no daemon found) */
  84. # endif /* DEFAULT_DAEMON not defined */
  85.  
  86. /* for console window on Suns */
  87. # ifndef SMALL_CONSOLE
  88. /* # define SMALL_CONSOLE " [cons]"    /**/
  89. # define SMALL_CONSOLE " [console]"    /* enuf room for this! */
  90. # endif /* SMALL_CONSOLE not defined */
  91.  
  92. # ifndef BIG_CONSOLE
  93. # define BIG_CONSOLE " [console]"
  94. # endif /* BIG_CONSOLE not defined */
  95.  
  96. # ifndef PTYPATH
  97. # define PTYPATH "/dev/ttyp1"        /* path for known pty-tty */
  98. # endif /* PTYPATH not defined */
  99.  
  100. # ifdef Umax
  101. # include <netdb.h>            /* for struct hostent */
  102. # include <sys/socket.h>        /* for AF_INET */
  103. # endif /* Umax defined */
  104.  
  105. # define USERLEN 32            /* max length of user string */
  106. # define LOCLEN 48            /* max length of ttyloc string */
  107.  
  108. LOCAL char location[LOCLEN];        /* return value goes here */
  109. LOCAL char userstr[USERLEN];        /* user string (if any) here */
  110. LOCAL int ptymajor = -1;        /* major device number for tty/pty */
  111. LOCAL int readfile;            /* ture if we have read LOCFILE */
  112.  
  113. EXTERN char *zup(), *cleanup();        /* from string.c */
  114. EXTERN char *locname();            /* from locname.c */
  115. EXTERN char *netlocname();        /* from locname.c */
  116.  
  117. # ifdef sun
  118. EXTERN dev_t consdev, rconsdev;        /* current and real console devs */
  119. # define ISCONS(d) (d == consdev && consdev != rconsdev)
  120. # else  /* sun not defined */
  121. # define ISCONS(d) 0            /* smart compilers will remove this */
  122. # endif /* sun not defined */
  123.  
  124. LOCAL BOOL onapty( u )
  125.     LUSER *u;
  126. {
  127.     struct stat stb;
  128.  
  129.     if( ptymajor == -1 ) {        /* first time? */
  130.     if( stat(PTYPATH, &stb) == 0 )
  131.         ptymajor = major( stb.st_rdev );
  132.     else {
  133.         ptymajor = -2;
  134.         return( FALSE );
  135.     }
  136.     } /* first time? */
  137.  
  138.     if( ptymajor > 0 && ptymajor == major( u->u_ttydev ) )
  139.     return( TRUE );
  140.     return( FALSE );
  141. } /* onapty */
  142.  
  143. # ifdef ultrix
  144. LOCAL BOOL onlat( u )
  145.     LUSER *u;
  146. {
  147. # ifdef USE_DEVIOCGET
  148. /* This is soooo dumb.
  149.  * - Requires a fd (so only works when have write access to ttys!)
  150.  * - returns *STRINGS*
  151.  * - **FAILS** on pty's (Not a typewriter!)
  152.  *
  153.  * What twinkies.
  154.  *
  155.  * This will only be of any use if finger runs setuid to root.
  156.  * (setgid group tty is pointless, since finger needs group kmem
  157.  * as well).  This is not (known to be) dangerous, just tasteless!
  158.  *
  159.  * Probably better to just put all LAT lines (!) into /etc/(n)ttyloc.
  160.  */
  161.     int fd, flag;
  162.     char path[ 32 ];
  163.     struct devget dg;
  164.     static int checked = FALSE, notty = FALSE;
  165.  
  166.     strcpy( path, "/dev/" );
  167.     strcat( path, u->u_line );
  168.  
  169.     if( !checked ) {            /* check if we have a tty */
  170.     if( (f = open( "/dev/tty", 1)) >= 0 )
  171.         close( f );            /* yes we do */
  172.     else
  173.         notty = TRUE;        /* we don't */
  174.     checked = TRUE;
  175.     }
  176.  
  177.     if( (fd = open (argv[i], O_RDONLY|O_NDELAY)) < 0 &&
  178.        (fd = open (argv[i], O_WRONLY|O_NDELAY)) < 0 )
  179.     return( FALSE );
  180.  
  181.     flag = ioctl( fd, DEVIOCGET, &dg ) == 0 &&
  182.     strcmp( dg.interface, DEV_LAT ) == 0;
  183.  
  184.     (void) close( fd );
  185.  
  186.     /* flush tty association -- so fingerd doesn't get attached!! */
  187.     if( notty && (fd = open( "/dev/tty", 1)) >= 0 ) { /* if no tty */
  188.     ioctl( fd, TIOCNOTTY, 0 );    /* flush assoc with one */
  189.     close( f );            /* we just opened */
  190.     }
  191.  
  192.     return( flag );
  193. # else  /* USE_DEVIOCGET not defined */
  194.     if( latmajor == -1 ) {        /* first time? */
  195.     if( stat(LATPATH, &stb) == 0 )
  196.         latmajor = major( stb.st_rdev );
  197.     else {
  198.         latmajor = -2;
  199.         return( FALSE );
  200.     }
  201.     } /* first time? */
  202.  
  203.     if( latmajor > 0 && latmajor == major( u->u_ttydev ) )
  204.     return( TRUE );
  205.     return( FALSE );
  206. # endif /* USE_DEVIOCGET not defined */
  207. } /* onlat */
  208. # endif /* ultrix defined */
  209.  
  210. GLOBAL void inittylocs() {
  211.     if( !readfile ) {
  212.     readfile = 1;
  213.     if( readnewttylocfile() < 1 ) {
  214.         int i;
  215.         i = readttylocfile();
  216. # ifdef TTYENT
  217.         if( i < 1 )
  218.         i = readttyents();
  219. # endif /* TTYENT defined */
  220.     }
  221.     } /* try reading a ttyloc file */
  222. } /* inittylocs */
  223.  
  224. GLOBAL char *getttyloc( u )        /* return ttyloc string */
  225.     LUSER *u;
  226. {
  227.     int f, cc;            /* file */
  228.     char *fname, *shortstr, *longstr;
  229.     TTYLOC *tp;
  230.  
  231.     userstr[0] = EOS;
  232.     if( !readfile )
  233.     inittylocs();
  234.  
  235.     if( !u->u_sw.sw_location ) {
  236.     fname = locname(u->u_line); /* try to find file in spool area */
  237.     if( (f = open(fname, 0)) >= 0 ) {
  238.         struct stat stb;
  239.         if( fstat(f, &stb) == 0 && stb.st_mtime > u->u_time ) {
  240. # ifdef DEBUG
  241.         puts(fname);
  242. # endif /* DEBUG defined */
  243.         cc = read(f, userstr, USERLEN-1);
  244.         if( cc > 0 )
  245.             userstr[cc] = EOS;
  246.         } /* fstat and recent */
  247.         close(f);
  248.         cleanup(userstr);
  249.     } /* fname open */
  250.  
  251. # ifdef OTTYLOC                /* old style per user ttyloc */
  252.     /* try ~/.ttyloc file -- this could be cached in the luser struct */
  253.     if( userstr[0] == EOS && u->u_person != NULL) {
  254.         strcpy(fname, u->u_person->p_home);
  255.         strcat(fname, "/.ttyloc");
  256.         if( (f = open(fname, 0)) >= 0 ) {
  257.         cc = read(f, userstr, USERLEN-1);
  258.         userstr[cc] = EOS;
  259.         }
  260.         close(f);
  261.         cleanup(userstr);
  262.     } /* no userstr yet, have person */
  263. # endif /* OTTYLOC defined */
  264.     } /* not sw_location */
  265.  
  266.     shortstr = longstr = NULL;
  267.  
  268.     if( u->u_host[0] != EOS )
  269.     checkhost( u->u_host, sizeof( u->u_host ) );
  270. # ifdef Umax
  271.      else if( u->u_ttyaddr != 0 ) {
  272.     struct hostent *hp;
  273.     if( (hp = gethostbyaddr( &u->u_ttyaddr,
  274.                 sizeof( u->u_ttyaddr ), AF_INET )) != NULL )
  275.         strzcpy( u->u_host, hp->h_name, sizeof( u->u_host ) - 1 );
  276.     else
  277.         strzcpy( u->u_host, inet_ntoa( u->u_ttyaddr ) );
  278.     } /* no host */
  279. # endif /* Umax defined */
  280.  
  281.     if( u->u_host[0] != EOS ) {        /* have host? */
  282.     register char *cp;
  283.  
  284. # ifndef NO_X_WINDOWS
  285.     int display_number, decnet_display, screen_number;
  286. # define NOT_FOUND -1
  287.     display_number = screen_number = NOT_FOUND;
  288.  
  289.     /* This botches on XNS addresses net:addr */
  290.     if( (cp = index(u->u_host, ':')) != NULL ) { /* host:display */
  291.         *cp++ = EOS;        /* blast first ':' */
  292.  
  293.         if( *cp == ':' ) {        /* second ':' ? (DECnet) */
  294.         cp++;            /* advance. */
  295.         decnet_display = TRUE;
  296.         } /* second ':' */
  297.         else
  298.         decnet_display = FALSE;
  299.  
  300.         if( isdigit( *cp ) ) {    /* digits after ':'? */
  301.         display_number = 0;
  302.         do
  303.             display_number = display_number * 10 + *cp++ - '0';
  304.         while( isdigit(*cp) );
  305.  
  306.         if( *cp == '.' ) {    /* display terminated by DOT? */
  307.             screen_number = 0;    /* X11 "screen number" */
  308.             cp++;        /* skip dot */
  309.  
  310.             while( isdigit(*cp) )
  311.             screen_number = screen_number * 10 + *cp++ - '0';
  312.         } /* collect screen */    
  313.         } /* digits after ':' */
  314.     } /* found : */
  315. # endif /* NO_X_WINDOWS not defined */
  316.  
  317.     if( userstr[0] != EOS ) {    /* have user str? */
  318.         undomain( u->u_host, TRUE ); /* remove domains and prefixes */
  319.  
  320.         longstr = userstr;
  321.         shortstr = NULL;
  322.  
  323. # ifndef NO_X_WINDOWS
  324.         if( display_number != NOT_FOUND ) {
  325.         char screen[ 15 ];
  326.         if( screen_number != NOT_FOUND && screen_number != 0 )
  327.             sprintf( screen, ".%d", screen_number );
  328.         else
  329.             screen[0] = EOS;
  330.  
  331.         sprintf(location, "%s:%s%d%s",
  332.             u->u_host,
  333.             (decnet_display ? ":" : ""),
  334.             display_number,
  335.             screen );
  336.         shortstr = location;
  337.         } /* display != -1 */
  338. # endif /* NO_X_WINDOWS not defined */
  339. # ifdef Umax
  340.         else if( u->u_ttyaddr != 0 ) {
  341.         register int i;
  342.         char *lt;
  343.         static char *ltt[] = {
  344.             "", "lp",        /* BSD style driver */
  345.             "V", "Vlp" };    /* SYSV style */
  346.  
  347.         i = u->u_ttytype;
  348.         if( i < 1 || i-1 > ( sizeof( ltt ) / sizeof( char * ) ) )
  349.             lt = "??";
  350.         else
  351.             lt = ltt[ i-1 ];
  352.         sprintf(location, "%s_%s%d", /* A la ANF-10 !*/
  353.             HZUP( u->u_host ),
  354.             lt,
  355.             u->u_ttynum );
  356.         shortstr = location;
  357.         } /* ttyaddr != 0 */
  358. # endif /* Umax defined */
  359. # ifdef ultrix
  360.         else if( onlat( u ) )
  361.         shortstr = "LAT";
  362. # endif /* ultrix defined */
  363.         else
  364.         shortstr = HZUP( u->u_host );
  365.     } /* host and user str */
  366.     else {                /* host, no user string */
  367.         undomain( u->u_host, FALSE ); /* just remove domains */
  368. # ifndef NO_X_WINDOWS
  369.         if( display_number != NOT_FOUND ) { /* have x display number */
  370.         char screen[ 15 ], *xv;    /* X11 */
  371.         screen[0] = EOS;
  372.         xv = X10_STR;
  373.         if( screen_number != NOT_FOUND ) {
  374.             xv = X11_STR;
  375.             if( screen_number != 0 )
  376.             sprintf( screen, " screen %d",
  377.                 screen_number ); /* woof */
  378.         }
  379. # ifdef X_LOCAL
  380.         if( casecmp( u->u_host, "UNIX" ) )
  381.             sprintf( location, "Local %s display %d%s%s",
  382.                 xv, display_number, screen,
  383.                 (ISCONS(u->u_ttydev) ? SMALL_CONSOLE : "") );
  384.         else
  385. # endif /* X_LOCAL defined */
  386.             sprintf(location, "%s (%s%s display %d%s)%s",
  387.                 u->u_host,    /* zup'ed already */
  388.                 (decnet_display ? "DECnet " : ""), /* we use TCP */
  389.                 xv, display_number, screen,
  390.                 (ISCONS(u->u_ttydev) ? SMALL_CONSOLE : "") );
  391.         return( location );
  392.         } /* have display number */
  393.         else
  394. # endif /* NO_X_WINDOWS not defined */
  395. # ifdef Umax
  396.         if( u->u_ttyaddr != 0 ) {    /* host, no user, is annex device */
  397.         register int i;
  398.         char *lt;
  399.         static char *ltt[] = {
  400.             "port", "lp",    /* BSD devices */
  401.             "Vport", "SYSV lp"    /* SYS V devices */
  402.             };
  403.  
  404. # ifdef NETLOC
  405.         int f;
  406.         char portname[ 50 ];
  407.  
  408.         sprintf( portname, "%s:port%d", u->u_host, u->u_ttynum );
  409.         fname = netlocname( portname );
  410.         if( (f = open(fname, 0)) >= 0 ) {
  411.             struct stat stb;
  412.             if( fstat(f, &stb) == 0 && stb.st_mtime > u->u_time ) {
  413.             cc = read(f, userstr, USERLEN-1);
  414.             userstr[cc] = EOS;
  415.             }
  416.             close(f);
  417.             cleanup(userstr);
  418.             if( userstr[0] != EOS )
  419.             return( userstr );
  420.         } /* open ok */
  421. # endif /* NETLOC defined */
  422.  
  423.         i = u->u_ttytype;
  424.         if( i < 1 || i-1 > ( sizeof( ltt ) / sizeof( char * ) ) )
  425.             lt = "??";
  426.         else
  427.             lt = ltt[ i-1 ];
  428.  
  429.         sprintf(location, "%s (Annex Call) %s%d",
  430.             HZUP( u->u_host ),
  431.             lt,
  432.             u->u_ttynum );
  433.         return( location );
  434.         } /* host, no user str, is annex */
  435.         else
  436. # endif /* Umax defined */
  437. # ifdef ultrix
  438.         else if( onlat( u ) ) {    /* host, no user str, LAT */
  439.         sprintf( location, "%s (LAT)", HZUP( u->u_host ) );
  440.         return( location );
  441.         } /* host, no user str, LAT */
  442. # endif /* ultrix defined */
  443.         {                /* host, nothing unusual */
  444.         char *dp;
  445.         if( u->u_daemon != NULL )
  446.             dp = u->u_daemon->d_long;
  447.         else if( u->u_daemonp != NULL &&
  448.             u->u_daemonp->pr_cmd[0] != EOS )
  449.             dp = u->u_daemonp->pr_cmd;
  450.         else
  451.             dp = DEFAULT_DAEMON;
  452.         sprintf( location, "%s (%s)", HZUP( u->u_host ), dp );
  453.         return( location );
  454.         } /* host, nothing unusual */
  455.     } /* host, no user string */
  456.     } /* have host */
  457.     else if( onapty( u ) ) {        /* is pty, no host */
  458.     if( userstr[0] != EOS ) {    /* pty, no host, user string */
  459.         if( u->u_daemon != NULL )
  460.         shortstr = u->u_daemon->d_short;
  461.         else if( u->u_daemonp != NULL &&
  462.             u->u_daemonp->pr_cmd[0] != EOS )
  463.         shortstr = u->u_daemonp->pr_cmd;
  464.         else if( ISCONS(u->u_ttydev) )
  465.         shortstr = "CONS";
  466.         else
  467.         shortstr = "PTY";    /* sigh */
  468.         longstr = userstr;
  469.     } /* pty, nohost, user string */
  470.     else if( u->u_daemon != NULL ) { /* pty, nohost, nouser, daemon */
  471.         char *cons;
  472.         if( ISCONS(u->u_ttydev) )    /* pty nohost nouser daemon cons */
  473.             cons = SMALL_CONSOLE;
  474.         else
  475.             cons = "";
  476.         sprintf( location, "via %s%s", u->u_daemon->d_long, cons );
  477.         return( location );
  478.     } /* pty, nohost, nouser, daemon entry */
  479.     else if( u->u_daemonp != NULL && u->u_daemonp->pr_cmd[0] != EOS ) {
  480.         /* pty, nohost, nouser, daemon process (not in daemon table) */
  481.         char *cons;
  482.         if( ISCONS(u->u_ttydev) )
  483.         cons = BIG_CONSOLE;
  484.         else
  485.         cons = "";
  486.         sprintf( location, "child of %s%s", u->u_daemonp->pr_cmd, cons );
  487.         return( location );
  488.     } /* pty, nohost, nouser, daemon process */
  489.     else if( ISCONS(u->u_ttydev) )    /* pty, nohost, nouser, nodaemon, con*/
  490.         return( "Pseudo Console" );
  491. # ifndef NO_X_WINDOWS
  492.     else if( strcmp( u->u_line, "ttyv0" ) == 0 )
  493.         return( "X login window");
  494. # endif /* NO_X_WINDOWS not defined */
  495.     else                /* pty, nohost, nouser, nodae, nocon */
  496.         return( "Pseudo Terminal" );
  497.     } /* is pty */
  498. # ifdef ultrix
  499.     else if( onlat( u ) ) {        /* no host, LAT */
  500.     if( userstr[0] == EOS )        /* LAT, no host, no userstr */
  501.         return( "via LAT" );
  502.     else
  503.         shortstr = "LAT";
  504.     } /* LAT, no host */
  505. # endif /* ultrix defined */
  506.     else {                /* normal line (no host, no pty) */
  507. # ifdef NETLOC
  508.     if( userstr[0] == EOS ) {    /* normal line, no userstr */
  509.         fname = netlocname(u->u_line); /* try to find file in spool area */
  510.         f = open( fname, 0 );
  511.         if( f >= 0 ) {
  512.         struct stat stb;
  513.         if( fstat(f, &stb) == 0 && stb.st_mtime > u->u_time ) {
  514.             cc = read(f, userstr, USERLEN-1);
  515.             userstr[cc] = EOS;
  516.         }
  517.         close(f);
  518.         cleanup( userstr );
  519.         } /* opened file */
  520.     } /* no userstr */
  521. # endif /* NETLOC defined */
  522.  
  523.     if( (tp = findttyloc( u->u_line )) != NULL ) { /* get from file */
  524.         if( userstr[0] != EOS ) {    /* found ttyloc, have userstr */
  525.         shortstr = tp->t_short;
  526.         longstr = userstr;
  527.         } /* found ttyloc, have userstr */
  528.         else if( tp->t_locn != NULL )
  529.         return( tp->t_locn );
  530.         /* fall back on t_short??? WISH */
  531.     } /* found tp entry */
  532. # ifdef UmaxV
  533.     else if( u->u_line[0] == 'r' && u->u_line[1] == 't' ) {
  534.         /* mls rdp device; rtAAPPSS */
  535.         if( userstr[0] == EOS ) {
  536.         if( strlen( u->u_line ) == 7 ) {
  537.             char session[ 10 ];
  538.             
  539.             if( u->u_line[6] != '0' )
  540.             sprintf( session, " session %c",
  541.                 u->u_line[6] );
  542.             else
  543.             session[0] = EOS;
  544.  
  545.             sprintf( location, "annex %c%c port %c%c%s",
  546.                 u->u_line[2], u->u_line[3],
  547.                 u->u_line[4], u->u_line[5],
  548.                 session );
  549.             return( location );
  550.         }
  551.         else
  552.             return( "annex RDP connection" );
  553.         }
  554.         else
  555.         shortstr = "annex";    /* "RDP" */
  556.  
  557.     }
  558.     else if( u->u_line[0] == 'R' && u->u_line[1] == 'T' ) {
  559.         /* mls rdp device RTxxxxx for unknown annex */
  560.         if( userstr[0] == EOS ) {
  561.         sprintf( location, "foreign annex %s",
  562.             u->u_line+2 );
  563.         return( location );
  564.         }
  565.         else
  566.         shortstr = "annex";
  567.     }
  568. # endif /* UmaxV defined */
  569.     else if( userstr[0] != EOS )
  570.         return( userstr );
  571.     } /* normal line (no host, no user) */
  572.  
  573.     if( longstr == NULL ) {
  574.     if( strcmp( u->u_line, "console" ) == 0
  575. # ifdef AIX3
  576.         || strcmp( u->u_line, "hft/1" ) == 0
  577. # endif /* AIX3 defined */
  578.         )
  579.         longstr = "Console Terminal"; /* physical console */
  580.     }
  581.  
  582.     if( shortstr != NULL ) {        /* have short string */
  583.     if( longstr != NULL ) {
  584.         /* was once ':' */
  585.         sprintf( location, "%s; %s", shortstr, longstr );
  586.         return( location );
  587.     }
  588.     else
  589.         return( shortstr );
  590.     } /* short str */
  591.     else if( longstr != NULL )
  592.     return( longstr );
  593.     return( "Unknown" );
  594. } /* getttyloc */
  595.  
  596. /*
  597.  * Local variables:
  598.  * comment-column: 40
  599.  * End:
  600.  */
  601.