tc.func.c revision 83098
183098Smp/* $Header: /src/pub/tcsh/tc.func.c,v 3.97 2001/08/28 23:13:44 christos Exp $ */ 259243Sobrien/* 359243Sobrien * tc.func.c: New tcsh builtins. 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 1759243Sobrien * 3. All advertising materials mentioning features or use of this software 1859243Sobrien * must display the following acknowledgement: 1959243Sobrien * This product includes software developed by the University of 2059243Sobrien * California, Berkeley and its contributors. 2159243Sobrien * 4. Neither the name of the University nor the names of its contributors 2259243Sobrien * may be used to endorse or promote products derived from this software 2359243Sobrien * without specific prior written permission. 2459243Sobrien * 2559243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2659243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2759243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2859243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2959243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3059243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3159243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3259243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 3359243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3459243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3559243Sobrien * SUCH DAMAGE. 3659243Sobrien */ 3759243Sobrien#include "sh.h" 3859243Sobrien 3983098SmpRCSID("$Id: tc.func.c,v 3.97 2001/08/28 23:13:44 christos Exp $") 4059243Sobrien 4159243Sobrien#include "ed.h" 4259243Sobrien#include "ed.defns.h" /* for the function names */ 4359243Sobrien#include "tw.h" 4459243Sobrien#include "tc.h" 4569408Sache#ifdef WINNT_NATIVE 4659243Sobrien#include "nt.const.h" 4769408Sache#endif /* WINNT_NATIVE */ 4859243Sobrien 4959243Sobrien#ifdef AFS 5059243Sobrien#define PASSMAX 16 5159243Sobrien#include <afs/stds.h> 5259243Sobrien#include <afs/kautils.h> 5359243Sobrienlong ka_UserAuthenticateGeneral(); 5459243Sobrien#else 5559243Sobrien#ifndef PASSMAX 5659243Sobrien#define PASSMAX 8 5759243Sobrien#endif 5859243Sobrien#endif /* AFS */ 5959243Sobrien 6059243Sobrien#ifdef TESLA 6159243Sobrienextern int do_logout; 6259243Sobrien#endif /* TESLA */ 6359243Sobrienextern time_t t_period; 6459243Sobrienextern int just_signaled; 6559243Sobrienstatic bool precmd_active = 0; 6683098Smpstatic bool jobcmd_active = 0; /* GrP */ 6759243Sobrienstatic bool postcmd_active = 0; 6859243Sobrienstatic bool periodic_active = 0; 6959243Sobrienstatic bool cwdcmd_active = 0; /* PWP: for cwd_cmd */ 7059243Sobrienstatic bool beepcmd_active = 0; 7159243Sobrienstatic signalfun_t alm_fun = NULL; 7259243Sobrien 7359243Sobrienstatic void auto_logout __P((int)); 7459243Sobrienstatic char *xgetpass __P((char *)); 7559243Sobrienstatic void auto_lock __P((int)); 7659243Sobrien#ifdef BSDJOBS 7759243Sobrienstatic void insert __P((struct wordent *, bool)); 7859243Sobrienstatic void insert_we __P((struct wordent *, struct wordent *)); 7959243Sobrienstatic int inlist __P((Char *, Char *)); 8059243Sobrien#endif /* BSDJOBS */ 8159243Sobrienstruct tildecache; 8259243Sobrienstatic int tildecompare __P((struct tildecache *, struct tildecache *)); 8359243Sobrienstatic Char *gethomedir __P((Char *)); 8459243Sobrien#ifdef REMOTEHOST 8559243Sobrienstatic sigret_t palarm __P((int)); 8659243Sobrienstatic void getremotehost __P((void)); 8759243Sobrien#endif /* REMOTEHOST */ 8859243Sobrien 8959243Sobrien/* 9059243Sobrien * Tops-C shell 9159243Sobrien */ 9259243Sobrien 9359243Sobrien/* 9461524Sobrien * expand_lex: Take the given lex and put an expanded version of it in 9561524Sobrien * the string buf. First guy in lex list is ignored; last guy is ^J 9661524Sobrien * which we ignore. Only take lex'es from position 'from' to position 9761524Sobrien * 'to' inclusive 9861524Sobrien * 9961524Sobrien * Note: csh sometimes sets bit 8 in characters which causes all kinds 10061524Sobrien * of problems if we don't mask it here. Note: excl's in lexes have been 10161524Sobrien * un-back-slashed and must be re-back-slashed 10261524Sobrien * 10359243Sobrien * (PWP: NOTE: this returns a pointer to the END of the string expanded 10459243Sobrien * (in other words, where the NUL is).) 10559243Sobrien */ 10659243Sobrien/* PWP: this is a combination of the old sprlex() and the expand_lex from 10759243Sobrien the magic-space stuff */ 10859243Sobrien 10959243SobrienChar * 11059243Sobrienexpand_lex(buf, bufsiz, sp0, from, to) 11159243Sobrien Char *buf; 11259243Sobrien size_t bufsiz; 11359243Sobrien struct wordent *sp0; 11459243Sobrien int from, to; 11559243Sobrien{ 11659243Sobrien register struct wordent *sp; 11759243Sobrien register Char *s, *d, *e; 11859243Sobrien register Char prev_c; 11959243Sobrien register int i; 12059243Sobrien 12169408Sache /* 12269408Sache * Make sure we have enough space to expand into. E.g. we may have 12369408Sache * "a|b" turn to "a | b" (from 3 to 5 characters) which is the worst 12469408Sache * case scenario (even "a>&! b" turns into "a > & ! b", i.e. 6 to 9 12569408Sache * characters -- am I missing any other cases?). 12669408Sache */ 12769408Sache bufsiz = bufsiz / 2; 12869408Sache 12959243Sobrien buf[0] = '\0'; 13059243Sobrien prev_c = '\0'; 13159243Sobrien d = buf; 13259243Sobrien e = &buf[bufsiz]; /* for bounds checking */ 13359243Sobrien 13459243Sobrien if (!sp0) 13559243Sobrien return (buf); /* null lex */ 13659243Sobrien if ((sp = sp0->next) == sp0) 13759243Sobrien return (buf); /* nada */ 13859243Sobrien if (sp == (sp0 = sp0->prev)) 13959243Sobrien return (buf); /* nada */ 14059243Sobrien 14159243Sobrien for (i = 0; i < NCARGS; i++) { 14259243Sobrien if ((i >= from) && (i <= to)) { /* if in range */ 14359243Sobrien for (s = sp->word; *s && d < e; s++) { 14459243Sobrien /* 14559243Sobrien * bugfix by Michael Bloom: anything but the current history 14659243Sobrien * character {(PWP) and backslash} seem to be dealt with 14759243Sobrien * elsewhere. 14859243Sobrien */ 14959243Sobrien if ((*s & QUOTE) 15059243Sobrien && (((*s & TRIM) == HIST) || 15159243Sobrien (((*s & TRIM) == '\'') && (prev_c != '\\')) || 15259243Sobrien (((*s & TRIM) == '\"') && (prev_c != '\\')) || 15359243Sobrien (((*s & TRIM) == '\\') && (prev_c != '\\')))) { 15459243Sobrien *d++ = '\\'; 15559243Sobrien } 15659243Sobrien if (d < e) 15759243Sobrien *d++ = (*s & TRIM); 15859243Sobrien prev_c = *s; 15959243Sobrien } 16059243Sobrien if (d < e) 16159243Sobrien *d++ = ' '; 16259243Sobrien } 16359243Sobrien sp = sp->next; 16459243Sobrien if (sp == sp0) 16559243Sobrien break; 16659243Sobrien } 16759243Sobrien if (d > buf) 16859243Sobrien d--; /* get rid of trailing space */ 16959243Sobrien 17059243Sobrien return (d); 17159243Sobrien} 17259243Sobrien 17359243SobrienChar * 17459243Sobriensprlex(buf, bufsiz, sp0) 17559243Sobrien Char *buf; 17659243Sobrien size_t bufsiz; 17759243Sobrien struct wordent *sp0; 17859243Sobrien{ 17959243Sobrien Char *cp; 18059243Sobrien 18159243Sobrien cp = expand_lex(buf, bufsiz, sp0, 0, NCARGS); 18259243Sobrien *cp = '\0'; 18359243Sobrien return (buf); 18459243Sobrien} 18559243Sobrien 18659243Sobrien 18759243SobrienChar * 18859243SobrienItoa(n, s, min_digits, attributes) 18959243Sobrien int n; 19059243Sobrien Char *s; 19159243Sobrien int min_digits, attributes; 19259243Sobrien{ 19359243Sobrien /* 19459243Sobrien * The array size here is derived from 19559243Sobrien * log8(UINT_MAX) 19659243Sobrien * which is guaranteed to be enough for a decimal 19759243Sobrien * representation. We add 1 because integer divide 19859243Sobrien * rounds down. 19959243Sobrien */ 20059243Sobrien#ifndef CHAR_BIT 20159243Sobrien# define CHAR_BIT 8 20259243Sobrien#endif 20359243Sobrien Char buf[CHAR_BIT * sizeof(int) / 3 + 1]; 20459243Sobrien Char *p; 20559243Sobrien unsigned int un; /* handle most negative # too */ 20659243Sobrien int pad = (min_digits != 0); 20759243Sobrien 20859243Sobrien if (sizeof(buf) - 1 < min_digits) 20959243Sobrien min_digits = sizeof(buf) - 1; 21059243Sobrien 21159243Sobrien un = n; 21259243Sobrien if (n < 0) { 21359243Sobrien un = -n; 21459243Sobrien *s++ = '-'; 21559243Sobrien } 21659243Sobrien 21759243Sobrien p = buf; 21859243Sobrien do { 21959243Sobrien *p++ = un % 10 + '0'; 22059243Sobrien un /= 10; 22159243Sobrien } while ((pad && --min_digits > 0) || un != 0); 22259243Sobrien 22359243Sobrien while (p > buf) 22459243Sobrien *s++ = *--p | attributes; 22559243Sobrien 22659243Sobrien *s = '\0'; 22759243Sobrien return s; 22859243Sobrien} 22959243Sobrien 23059243Sobrien 23159243Sobrien/*ARGSUSED*/ 23259243Sobrienvoid 23359243Sobriendolist(v, c) 23459243Sobrien register Char **v; 23559243Sobrien struct command *c; 23659243Sobrien{ 23759243Sobrien int i, k; 23859243Sobrien struct stat st; 23959243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 24059243Sobrien extern bool dspmbyte_ls; 24159243Sobrien#endif 24259243Sobrien#ifdef COLOR_LS_F 24359243Sobrien extern bool color_context_ls; 24459243Sobrien#endif /* COLOR_LS_F */ 24559243Sobrien 24659243Sobrien USE(c); 24759243Sobrien if (*++v == NULL) { 24859243Sobrien (void) t_search(STRNULL, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0); 24959243Sobrien return; 25059243Sobrien } 25159243Sobrien gflag = 0; 25259243Sobrien tglob(v); 25359243Sobrien if (gflag) { 25459243Sobrien v = globall(v); 25559243Sobrien if (v == 0) 25659243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 25759243Sobrien } 25859243Sobrien else 25959243Sobrien v = gargv = saveblk(v); 26059243Sobrien trim(v); 26159243Sobrien for (k = 0; v[k] != NULL && v[k][0] != '-'; k++) 26259243Sobrien continue; 26359243Sobrien if (v[k]) { 26459243Sobrien /* 26559243Sobrien * We cannot process a flag therefore we let ls do it right. 26659243Sobrien */ 26759243Sobrien static Char STRls[] = {'l', 's', '\0'}; 26859243Sobrien static Char STRmCF[] = {'-', 'C', 'F', '\0', '\0' }; 26959243Sobrien Char *lspath; 27059243Sobrien struct command *t; 27159243Sobrien struct wordent cmd, *nextword, *lastword; 27259243Sobrien Char *cp; 27359243Sobrien struct varent *vp; 27459243Sobrien 27559243Sobrien#ifdef BSDSIGS 27659243Sobrien sigmask_t omask = 0; 27759243Sobrien 27859243Sobrien if (setintr) 27959243Sobrien omask = sigblock(sigmask(SIGINT)) & ~sigmask(SIGINT); 28059243Sobrien#else /* !BSDSIGS */ 28159243Sobrien (void) sighold(SIGINT); 28259243Sobrien#endif /* BSDSIGS */ 28359243Sobrien if (seterr) { 28459243Sobrien xfree((ptr_t) seterr); 28559243Sobrien seterr = NULL; 28659243Sobrien } 28759243Sobrien 28859243Sobrien lspath = STRls; 28959243Sobrien STRmCF[1] = 'C'; 29059243Sobrien STRmCF[3] = '\0'; 29159243Sobrien /* Look at listflags, to add -A to the flags, to get a path 29259243Sobrien of ls if necessary */ 29359243Sobrien if ((vp = adrof(STRlistflags)) != NULL && vp->vec[0] != STRNULL) { 29459243Sobrien if (vp->vec[1] != NULL && vp->vec[1][0] != '\0') 29559243Sobrien lspath = vp->vec[1]; 29659243Sobrien for (cp = vp->vec[0]; *cp; cp++) 29759243Sobrien switch (*cp) { 29859243Sobrien case 'x': 29959243Sobrien STRmCF[1] = 'x'; 30059243Sobrien break; 30159243Sobrien case 'a': 30259243Sobrien STRmCF[3] = 'a'; 30359243Sobrien break; 30459243Sobrien case 'A': 30559243Sobrien STRmCF[3] = 'A'; 30659243Sobrien break; 30759243Sobrien default: 30859243Sobrien break; 30959243Sobrien } 31059243Sobrien } 31159243Sobrien 31259243Sobrien cmd.word = STRNULL; 31359243Sobrien lastword = &cmd; 31459243Sobrien nextword = (struct wordent *) xcalloc(1, sizeof cmd); 31559243Sobrien nextword->word = Strsave(lspath); 31659243Sobrien lastword->next = nextword; 31759243Sobrien nextword->prev = lastword; 31859243Sobrien lastword = nextword; 31959243Sobrien nextword = (struct wordent *) xcalloc(1, sizeof cmd); 32059243Sobrien nextword->word = Strsave(STRmCF); 32159243Sobrien lastword->next = nextword; 32259243Sobrien nextword->prev = lastword; 32359243Sobrien#if defined(KANJI) && defined(SHORT_STRINGS) && defined(DSPMBYTE) 32459243Sobrien if (dspmbyte_ls) { 32559243Sobrien lastword = nextword; 32659243Sobrien nextword = (struct wordent *) xcalloc(1, sizeof cmd); 32759243Sobrien nextword->word = Strsave(STRmmliteral); 32859243Sobrien lastword->next = nextword; 32959243Sobrien nextword->prev = lastword; 33059243Sobrien } 33159243Sobrien#endif 33259243Sobrien#ifdef COLOR_LS_F 33359243Sobrien if (color_context_ls) { 33459243Sobrien lastword = nextword; 33559243Sobrien nextword = (struct wordent *) xcalloc(1, sizeof cmd); 33659243Sobrien nextword->word = Strsave(STRmmcolormauto); 33759243Sobrien lastword->next = nextword; 33859243Sobrien nextword->prev = lastword; 33959243Sobrien } 34059243Sobrien#endif /* COLOR_LS_F */ 34159243Sobrien lastword = nextword; 34259243Sobrien for (cp = *v; cp; cp = *++v) { 34359243Sobrien nextword = (struct wordent *) xcalloc(1, sizeof cmd); 34459243Sobrien nextword->word = Strsave(cp); 34559243Sobrien lastword->next = nextword; 34659243Sobrien nextword->prev = lastword; 34759243Sobrien lastword = nextword; 34859243Sobrien } 34959243Sobrien lastword->next = &cmd; 35059243Sobrien cmd.prev = lastword; 35159243Sobrien 35259243Sobrien /* build a syntax tree for the command. */ 35359243Sobrien t = syntax(cmd.next, &cmd, 0); 35459243Sobrien if (seterr) 35559243Sobrien stderror(ERR_OLD); 35659243Sobrien /* expand aliases like process() does */ 35759243Sobrien /* alias(&cmd); */ 35859243Sobrien /* execute the parse tree. */ 35959243Sobrien execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL); 36059243Sobrien /* done. free the lex list and parse tree. */ 36159243Sobrien freelex(&cmd), freesyn(t); 36259243Sobrien if (setintr) 36359243Sobrien#ifdef BSDSIGS 36459243Sobrien (void) sigsetmask(omask); 36559243Sobrien#else /* !BSDSIGS */ 36659243Sobrien (void) sigrelse(SIGINT); 36759243Sobrien#endif /* BSDSIGS */ 36859243Sobrien } 36959243Sobrien else { 37059243Sobrien Char *dp, *tmp, buf[MAXPATHLEN]; 37159243Sobrien 37259243Sobrien for (k = 0, i = 0; v[k] != NULL; k++) { 37359243Sobrien tmp = dnormalize(v[k], symlinks == SYM_IGNORE); 37459243Sobrien dp = &tmp[Strlen(tmp) - 1]; 37559243Sobrien if (*dp == '/' && dp != tmp) 37659243Sobrien#ifdef apollo 37759243Sobrien if (dp != &tmp[1]) 37859243Sobrien#endif /* apollo */ 37959243Sobrien *dp = '\0'; 38059243Sobrien if (stat(short2str(tmp), &st) == -1) { 38159243Sobrien if (k != i) { 38259243Sobrien if (i != 0) 38359243Sobrien xputchar('\n'); 38459243Sobrien print_by_column(STRNULL, &v[i], k - i, FALSE); 38559243Sobrien } 38659243Sobrien xprintf("%S: %s.\n", tmp, strerror(errno)); 38759243Sobrien i = k + 1; 38859243Sobrien } 38959243Sobrien else if (S_ISDIR(st.st_mode)) { 39059243Sobrien Char *cp; 39159243Sobrien 39259243Sobrien if (k != i) { 39359243Sobrien if (i != 0) 39459243Sobrien xputchar('\n'); 39559243Sobrien print_by_column(STRNULL, &v[i], k - i, FALSE); 39659243Sobrien } 39759243Sobrien if (k != 0 && v[1] != NULL) 39859243Sobrien xputchar('\n'); 39959243Sobrien xprintf("%S:\n", tmp); 40059243Sobrien for (cp = tmp, dp = buf; *cp; *dp++ = (*cp++ | QUOTE)) 40159243Sobrien continue; 40259243Sobrien if ( 40369408Sache#ifdef WINNT_NATIVE 40459243Sobrien (dp[-1] != (Char) (':' | QUOTE)) && 40569408Sache#endif /* WINNT_NATIVE */ 40659243Sobrien (dp[-1] != (Char) ('/' | QUOTE))) 40759243Sobrien *dp++ = '/'; 40859243Sobrien else 40959243Sobrien dp[-1] &= TRIM; 41059243Sobrien *dp = '\0'; 41159243Sobrien (void) t_search(buf, NULL, LIST, 0, TW_ZERO, 0, STRNULL, 0); 41259243Sobrien i = k + 1; 41359243Sobrien } 41459243Sobrien xfree((ptr_t) tmp); 41559243Sobrien } 41659243Sobrien if (k != i) { 41759243Sobrien if (i != 0) 41859243Sobrien xputchar('\n'); 41959243Sobrien print_by_column(STRNULL, &v[i], k - i, FALSE); 42059243Sobrien } 42159243Sobrien } 42259243Sobrien 42359243Sobrien if (gargv) { 42459243Sobrien blkfree(gargv); 42559243Sobrien gargv = 0; 42659243Sobrien } 42759243Sobrien} 42859243Sobrien 42959243Sobrienstatic char *defaulttell = "ALL"; 43059243Sobrienextern bool GotTermCaps; 43159243Sobrien 43259243Sobrien/*ARGSUSED*/ 43359243Sobrienvoid 43459243Sobriendotelltc(v, c) 43559243Sobrien register Char **v; 43659243Sobrien struct command *c; 43759243Sobrien{ 43859243Sobrien USE(c); 43959243Sobrien if (!GotTermCaps) 44059243Sobrien GetTermCaps(); 44159243Sobrien 44259243Sobrien /* 44359243Sobrien * Avoid a compiler bug on hpux 9.05 44459243Sobrien * Writing the following as func(a ? b : c) breaks 44559243Sobrien */ 44659243Sobrien if (v[1]) 44759243Sobrien TellTC(short2str(v[1])); 44859243Sobrien else 44959243Sobrien TellTC(defaulttell); 45059243Sobrien} 45159243Sobrien 45259243Sobrien/*ARGSUSED*/ 45359243Sobrienvoid 45459243Sobriendoechotc(v, c) 45559243Sobrien register Char **v; 45659243Sobrien struct command *c; 45759243Sobrien{ 45859243Sobrien if (!GotTermCaps) 45959243Sobrien GetTermCaps(); 46059243Sobrien EchoTC(++v); 46159243Sobrien} 46259243Sobrien 46359243Sobrien/*ARGSUSED*/ 46459243Sobrienvoid 46559243Sobriendosettc(v, c) 46659243Sobrien Char **v; 46759243Sobrien struct command *c; 46859243Sobrien{ 46959243Sobrien char tv[2][BUFSIZE]; 47059243Sobrien 47159243Sobrien if (!GotTermCaps) 47259243Sobrien GetTermCaps(); 47359243Sobrien 47459243Sobrien (void) strcpy(tv[0], short2str(v[1])); 47559243Sobrien (void) strcpy(tv[1], short2str(v[2])); 47659243Sobrien SetTC(tv[0], tv[1]); 47759243Sobrien} 47859243Sobrien 47959243Sobrien/* The dowhich() is by: 48059243Sobrien * Andreas Luik <luik@isaak.isa.de> 48159243Sobrien * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung 48259243Sobrien * Azenberstr. 35 48359243Sobrien * D-7000 Stuttgart 1 48459243Sobrien * West-Germany 48559243Sobrien * Thanks!! 48659243Sobrien */ 48759243Sobrienint 48859243Sobriencmd_expand(cmd, str) 48959243Sobrien Char *cmd; 49059243Sobrien Char *str; 49159243Sobrien{ 49259243Sobrien struct wordent lexp[3]; 49359243Sobrien struct varent *vp; 49459243Sobrien int rv = TRUE; 49559243Sobrien 49659243Sobrien lexp[0].next = &lexp[1]; 49759243Sobrien lexp[1].next = &lexp[2]; 49859243Sobrien lexp[2].next = &lexp[0]; 49959243Sobrien 50059243Sobrien lexp[0].prev = &lexp[2]; 50159243Sobrien lexp[1].prev = &lexp[0]; 50259243Sobrien lexp[2].prev = &lexp[1]; 50359243Sobrien 50459243Sobrien lexp[0].word = STRNULL; 50559243Sobrien lexp[2].word = STRret; 50659243Sobrien 50759243Sobrien if ((vp = adrof1(cmd, &aliases)) != NULL) { 50859243Sobrien if (str == NULL) { 50959243Sobrien xprintf(CGETS(22, 1, "%S: \t aliased to "), cmd); 51059243Sobrien blkpr(vp->vec); 51159243Sobrien xputchar('\n'); 51259243Sobrien } 51359243Sobrien else 51459243Sobrien blkexpand(vp->vec, str); 51559243Sobrien } 51659243Sobrien else { 51759243Sobrien lexp[1].word = cmd; 51859243Sobrien rv = tellmewhat(lexp, str); 51959243Sobrien } 52059243Sobrien return rv; 52159243Sobrien} 52259243Sobrien 52359243Sobrien 52459243Sobrien/*ARGSUSED*/ 52559243Sobrienvoid 52659243Sobriendowhich(v, c) 52759243Sobrien register Char **v; 52859243Sobrien struct command *c; 52959243Sobrien{ 53059243Sobrien int rv = TRUE; 53159243Sobrien USE(c); 53259243Sobrien 53359243Sobrien#ifdef notdef 53459243Sobrien /* 53559243Sobrien * We don't want to glob dowhich args because we lose quoteing 53659243Sobrien * E.g. which \ls if ls is aliased will not work correctly if 53759243Sobrien * we glob here. 53859243Sobrien */ 53959243Sobrien gflag = 0, tglob(v); 54059243Sobrien if (gflag) { 54159243Sobrien v = globall(v); 54259243Sobrien if (v == 0) 54359243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 54459243Sobrien } 54559243Sobrien else { 54659243Sobrien v = gargv = saveblk(v); 54759243Sobrien trim(v); 54859243Sobrien } 54959243Sobrien#endif 55059243Sobrien 55159243Sobrien while (*++v) 55259243Sobrien rv &= cmd_expand(*v, NULL); 55359243Sobrien 55459243Sobrien if (!rv) 55559243Sobrien set(STRstatus, Strsave(STR1), VAR_READWRITE); 55659243Sobrien 55759243Sobrien#ifdef notdef 55859243Sobrien /* Again look at the comment above; since we don't glob, we don't free */ 55959243Sobrien if (gargv) 56059243Sobrien blkfree(gargv), gargv = 0; 56159243Sobrien#endif 56259243Sobrien} 56359243Sobrien 56459243Sobrien/* PWP: a hack to start up your stopped editor on a single keystroke */ 56559243Sobrien/* jbs - fixed hack so it worked :-) 3/28/89 */ 56659243Sobrien 56759243Sobrienstruct process * 56859243Sobrienfind_stop_ed() 56959243Sobrien{ 57059243Sobrien register struct process *pp, *retp; 57159243Sobrien register char *ep, *vp, *cp, *p; 57259243Sobrien int epl, vpl, pstatus; 57359243Sobrien 57459243Sobrien if ((ep = getenv("EDITOR")) != NULL) { /* if we have a value */ 57559243Sobrien if ((p = strrchr(ep, '/')) != NULL) /* if it has a path */ 57659243Sobrien ep = p + 1; /* then we want only the last part */ 57759243Sobrien } 57859243Sobrien else 57959243Sobrien ep = "ed"; 58059243Sobrien 58159243Sobrien if ((vp = getenv("VISUAL")) != NULL) { /* if we have a value */ 58259243Sobrien if ((p = strrchr(vp, '/')) != NULL) /* and it has a path */ 58359243Sobrien vp = p + 1; /* then we want only the last part */ 58459243Sobrien } 58559243Sobrien else 58659243Sobrien vp = "vi"; 58759243Sobrien 58859243Sobrien for (vpl = 0; vp[vpl] && !Isspace(vp[vpl]); vpl++) 58959243Sobrien continue; 59059243Sobrien for (epl = 0; ep[epl] && !Isspace(ep[epl]); epl++) 59159243Sobrien continue; 59259243Sobrien 59359243Sobrien if (pcurrent == NULL) /* see if we have any jobs */ 59459243Sobrien return NULL; /* nope */ 59559243Sobrien 59659243Sobrien retp = NULL; 59759243Sobrien for (pp = proclist.p_next; pp; pp = pp->p_next) 59859243Sobrien if (pp->p_procid == pp->p_jobid) { 59959243Sobrien 60059243Sobrien /* 60159243Sobrien * Only foreground an edit session if it is suspended. Some GUI 60259243Sobrien * editors have may be happily running in a separate window, no 60359243Sobrien * point in foregrounding these if they're already running - webb 60459243Sobrien */ 60559243Sobrien pstatus = (int) (pp->p_flags & PALLSTATES); 60659243Sobrien if (pstatus != PINTERRUPTED && pstatus != PSTOPPED && 60759243Sobrien pstatus != PSIGNALED) 60859243Sobrien continue; 60959243Sobrien 61059243Sobrien p = short2str(pp->p_command); 61159243Sobrien /* get the first word */ 61259243Sobrien for (cp = p; *cp && !isspace((unsigned char) *cp); cp++) 61359243Sobrien continue; 61459243Sobrien *cp = '\0'; 61559243Sobrien 61659243Sobrien if ((cp = strrchr(p, '/')) != NULL) /* and it has a path */ 61759243Sobrien cp = cp + 1; /* then we want only the last part */ 61859243Sobrien else 61959243Sobrien cp = p; /* else we get all of it */ 62059243Sobrien 62159243Sobrien /* if we find either in the current name, fg it */ 62259243Sobrien if (strncmp(ep, cp, (size_t) epl) == 0 || 62359243Sobrien strncmp(vp, cp, (size_t) vpl) == 0) { 62459243Sobrien 62559243Sobrien /* 62659243Sobrien * If there is a choice, then choose the current process if 62759243Sobrien * available, or the previous process otherwise, or else 62859243Sobrien * anything will do - Robert Webb (robertw@mulga.cs.mu.oz.au). 62959243Sobrien */ 63059243Sobrien if (pp == pcurrent) 63159243Sobrien return pp; 63259243Sobrien else if (retp == NULL || pp == pprevious) 63359243Sobrien retp = pp; 63459243Sobrien } 63559243Sobrien } 63659243Sobrien 63759243Sobrien return retp; /* Will be NULL if we didn't find a job */ 63859243Sobrien} 63959243Sobrien 64059243Sobrienvoid 64159243Sobrienfg_proc_entry(pp) 64259243Sobrien register struct process *pp; 64359243Sobrien{ 64459243Sobrien#ifdef BSDSIGS 64559243Sobrien sigmask_t omask; 64659243Sobrien#endif 64759243Sobrien jmp_buf_t osetexit; 64859243Sobrien bool ohaderr; 64959243Sobrien Char oGettingInput; 65059243Sobrien 65159243Sobrien getexit(osetexit); 65259243Sobrien 65359243Sobrien#ifdef BSDSIGS 65459243Sobrien omask = sigblock(sigmask(SIGINT)); 65559243Sobrien#else 65659243Sobrien (void) sighold(SIGINT); 65759243Sobrien#endif 65859243Sobrien oGettingInput = GettingInput; 65959243Sobrien GettingInput = 0; 66059243Sobrien 66159243Sobrien ohaderr = haderr; /* we need to ignore setting of haderr due to 66259243Sobrien * process getting stopped by a signal */ 66359243Sobrien if (setexit() == 0) { /* come back here after pjwait */ 66459243Sobrien pendjob(); 66559243Sobrien (void) alarm(0); /* No autologout */ 66659243Sobrien if (!pstart(pp, 1)) { 66759243Sobrien pp->p_procid = 0; 66859243Sobrien stderror(ERR_BADJOB, pp->p_command, strerror(errno)); 66959243Sobrien } 67059243Sobrien pjwait(pp); 67159243Sobrien } 67259243Sobrien setalarm(1); /* Autologout back on */ 67359243Sobrien resexit(osetexit); 67459243Sobrien haderr = ohaderr; 67559243Sobrien GettingInput = oGettingInput; 67659243Sobrien 67759243Sobrien#ifdef BSDSIGS 67859243Sobrien (void) sigsetmask(omask); 67959243Sobrien#else /* !BSDSIGS */ 68059243Sobrien (void) sigrelse(SIGINT); 68159243Sobrien#endif /* BSDSIGS */ 68259243Sobrien 68359243Sobrien} 68459243Sobrien 68559243Sobrienstatic char * 68659243Sobrienxgetpass(prm) 68759243Sobrien char *prm; 68859243Sobrien{ 68959243Sobrien static char pass[PASSMAX + 1]; 69059243Sobrien int fd, i; 69159243Sobrien signalfun_t sigint; 69259243Sobrien 69359243Sobrien sigint = (signalfun_t) sigset(SIGINT, SIG_IGN); 69459243Sobrien (void) Rawmode(); /* Make sure, cause we want echo off */ 69559243Sobrien if ((fd = open("/dev/tty", O_RDWR)) == -1) 69659243Sobrien fd = SHIN; 69759243Sobrien 69859243Sobrien xprintf("%s", prm); flush(); 69959243Sobrien for (i = 0;;) { 70059243Sobrien if (read(fd, &pass[i], 1) < 1 || pass[i] == '\n') 70159243Sobrien break; 70259243Sobrien if (i < PASSMAX) 70359243Sobrien i++; 70459243Sobrien } 70559243Sobrien 70659243Sobrien pass[i] = '\0'; 70759243Sobrien 70859243Sobrien if (fd != SHIN) 70959243Sobrien (void) close(fd); 71059243Sobrien (void) sigset(SIGINT, sigint); 71159243Sobrien 71259243Sobrien return(pass); 71359243Sobrien} 71459243Sobrien 71559243Sobrien/* 71659243Sobrien * Ask the user for his login password to continue working 71759243Sobrien * On systems that have a shadow password, this will only 71859243Sobrien * work for root, but what can we do? 71959243Sobrien * 72059243Sobrien * If we fail to get the password, then we log the user out 72159243Sobrien * immediately 72259243Sobrien */ 72359243Sobrien/*ARGSUSED*/ 72459243Sobrienstatic void 72559243Sobrienauto_lock(n) 72659243Sobrien int n; 72759243Sobrien{ 72859243Sobrien#ifndef NO_CRYPT 72959243Sobrien 73059243Sobrien int i; 73159243Sobrien char *srpp = NULL; 73259243Sobrien struct passwd *pw; 73359243Sobrien#ifdef POSIX 73459243Sobrien extern char *crypt __P((const char *, const char *)); 73559243Sobrien#else 73659243Sobrien extern char *crypt __P(()); 73759243Sobrien#endif 73859243Sobrien 73959243Sobrien#undef XCRYPT 74059243Sobrien 74159243Sobrien#if defined(PW_AUTH) && !defined(XCRYPT) 74259243Sobrien 74359243Sobrien struct authorization *apw; 74459243Sobrien extern char *crypt16 __P((const char *, const char *)); 74559243Sobrien 74659243Sobrien# define XCRYPT(a, b) crypt16(a, b) 74759243Sobrien 74859243Sobrien if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */ 74959243Sobrien (apw = getauthuid(euid)) != NULL) /* enhanced ultrix passwd */ 75059243Sobrien srpp = apw->a_password; 75159243Sobrien 75259243Sobrien#endif /* PW_AUTH && !XCRYPT */ 75359243Sobrien 75459243Sobrien#if defined(PW_SHADOW) && !defined(XCRYPT) 75559243Sobrien 75659243Sobrien struct spwd *spw; 75759243Sobrien 75859243Sobrien# define XCRYPT(a, b) crypt(a, b) 75959243Sobrien 76059243Sobrien if ((pw = getpwuid(euid)) != NULL && /* effective user passwd */ 76159243Sobrien (spw = getspnam(pw->pw_name)) != NULL) /* shadowed passwd */ 76259243Sobrien srpp = spw->sp_pwdp; 76359243Sobrien 76459243Sobrien#endif /* PW_SHADOW && !XCRYPT */ 76559243Sobrien 76659243Sobrien#ifndef XCRYPT 76759243Sobrien 76859243Sobrien#define XCRYPT(a, b) crypt(a, b) 76959243Sobrien 77069408Sache#if !defined(__MVS__) 77159243Sobrien if ((pw = getpwuid(euid)) != NULL) /* effective user passwd */ 77259243Sobrien srpp = pw->pw_passwd; 77369408Sache#endif /* !MVS */ 77459243Sobrien 77559243Sobrien#endif /* !XCRYPT */ 77659243Sobrien 77759243Sobrien if (srpp == NULL) { 77859243Sobrien auto_logout(0); 77959243Sobrien /*NOTREACHED*/ 78059243Sobrien return; 78159243Sobrien } 78259243Sobrien 78359243Sobrien setalarm(0); /* Not for locking any more */ 78459243Sobrien#ifdef BSDSIGS 78559243Sobrien (void) sigsetmask(sigblock(0) & ~(sigmask(SIGALRM))); 78659243Sobrien#else /* !BSDSIGS */ 78759243Sobrien (void) sigrelse(SIGALRM); 78859243Sobrien#endif /* BSDSIGS */ 78959243Sobrien xputchar('\n'); 79059243Sobrien for (i = 0; i < 5; i++) { 79159243Sobrien const char *crpp; 79259243Sobrien char *pp; 79359243Sobrien#ifdef AFS 79459243Sobrien char *afsname; 79559243Sobrien Char *safs; 79659243Sobrien 79759243Sobrien if ((safs = varval(STRafsuser)) != STRNULL) 79859243Sobrien afsname = short2str(safs); 79959243Sobrien else 80059243Sobrien if ((afsname = getenv("AFSUSER")) == NULL) 80159243Sobrien afsname = pw->pw_name; 80259243Sobrien#endif 80359243Sobrien pp = xgetpass("Password:"); 80459243Sobrien 80559243Sobrien crpp = XCRYPT(pp, srpp); 80659243Sobrien if ((strcmp(crpp, srpp) == 0) 80759243Sobrien#ifdef AFS 80859243Sobrien || (ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, 80959243Sobrien afsname, /* name */ 81059243Sobrien NULL, /* instance */ 81159243Sobrien NULL, /* realm */ 81259243Sobrien pp, /* password */ 81359243Sobrien 0, /* lifetime */ 81459243Sobrien 0, 0, /* spare */ 81559243Sobrien NULL) /* reason */ 81659243Sobrien == 0) 81759243Sobrien#endif /* AFS */ 81859243Sobrien ) { 81959243Sobrien (void) memset(pp, 0, PASSMAX); 82059243Sobrien if (GettingInput && !just_signaled) { 82159243Sobrien (void) Rawmode(); 82259243Sobrien ClearLines(); 82359243Sobrien ClearDisp(); 82459243Sobrien Refresh(); 82559243Sobrien } 82659243Sobrien just_signaled = 0; 82759243Sobrien return; 82859243Sobrien } 82959243Sobrien xprintf(CGETS(22, 2, "\nIncorrect passwd for %s\n"), pw->pw_name); 83059243Sobrien } 83159243Sobrien#endif /* NO_CRYPT */ 83259243Sobrien auto_logout(0); 83359243Sobrien USE(n); 83459243Sobrien} 83559243Sobrien 83659243Sobrien 83759243Sobrienstatic void 83859243Sobrienauto_logout(n) 83959243Sobrien int n; 84059243Sobrien{ 84159243Sobrien USE(n); 84259243Sobrien xprintf("auto-logout\n"); 84359243Sobrien /* Don't leave the tty in raw mode */ 84459243Sobrien if (editing) 84559243Sobrien (void) Cookedmode(); 84659243Sobrien (void) close(SHIN); 84759243Sobrien set(STRlogout, Strsave(STRautomatic), VAR_READWRITE); 84859243Sobrien child = 1; 84959243Sobrien#ifdef TESLA 85059243Sobrien do_logout = 1; 85159243Sobrien#endif /* TESLA */ 85259243Sobrien GettingInput = FALSE; /* make flush() work to write hist files. Huber*/ 85359243Sobrien goodbye(NULL, NULL); 85459243Sobrien} 85559243Sobrien 85659243Sobriensigret_t 85759243Sobrien/*ARGSUSED*/ 85859243Sobrienalrmcatch(snum) 85959243Sobrienint snum; 86059243Sobrien{ 86159243Sobrien#ifdef UNRELSIGS 86259243Sobrien if (snum) 86359243Sobrien (void) sigset(SIGALRM, alrmcatch); 86459243Sobrien#endif /* UNRELSIGS */ 86559243Sobrien 86659243Sobrien (*alm_fun)(0); 86759243Sobrien 86859243Sobrien setalarm(1); 86959243Sobrien#ifndef SIGVOID 87059243Sobrien return (snum); 87159243Sobrien#endif /* !SIGVOID */ 87259243Sobrien} 87359243Sobrien 87459243Sobrien/* 87559243Sobrien * Karl Kleinpaste, 21oct1983. 87659243Sobrien * Added precmd(), which checks for the alias 87759243Sobrien * precmd in aliases. If it's there, the alias 87859243Sobrien * is executed as a command. This is done 87959243Sobrien * after mailchk() and just before print- 88059243Sobrien * ing the prompt. Useful for things like printing 88159243Sobrien * one's current directory just before each command. 88259243Sobrien */ 88359243Sobrienvoid 88459243Sobrienprecmd() 88559243Sobrien{ 88659243Sobrien#ifdef BSDSIGS 88759243Sobrien sigmask_t omask; 88859243Sobrien 88959243Sobrien omask = sigblock(sigmask(SIGINT)); 89059243Sobrien#else /* !BSDSIGS */ 89159243Sobrien (void) sighold(SIGINT); 89259243Sobrien#endif /* BSDSIGS */ 89359243Sobrien if (precmd_active) { /* an error must have been caught */ 89459243Sobrien aliasrun(2, STRunalias, STRprecmd); 89559243Sobrien xprintf(CGETS(22, 3, "Faulty alias 'precmd' removed.\n")); 89659243Sobrien goto leave; 89759243Sobrien } 89859243Sobrien precmd_active = 1; 89959243Sobrien if (!whyles && adrof1(STRprecmd, &aliases)) 90059243Sobrien aliasrun(1, STRprecmd, NULL); 90159243Sobrienleave: 90259243Sobrien precmd_active = 0; 90359243Sobrien#ifdef BSDSIGS 90459243Sobrien (void) sigsetmask(omask); 90559243Sobrien#else /* !BSDSIGS */ 90659243Sobrien (void) sigrelse(SIGINT); 90759243Sobrien#endif /* BSDSIGS */ 90859243Sobrien} 90959243Sobrien 91059243Sobrienvoid 91159243Sobrienpostcmd() 91259243Sobrien{ 91359243Sobrien#ifdef BSDSIGS 91459243Sobrien sigmask_t omask; 91559243Sobrien 91659243Sobrien omask = sigblock(sigmask(SIGINT)); 91759243Sobrien#else /* !BSDSIGS */ 91859243Sobrien (void) sighold(SIGINT); 91959243Sobrien#endif /* BSDSIGS */ 92059243Sobrien if (postcmd_active) { /* an error must have been caught */ 92159243Sobrien aliasrun(2, STRunalias, STRpostcmd); 92259243Sobrien xprintf(CGETS(22, 3, "Faulty alias 'postcmd' removed.\n")); 92359243Sobrien goto leave; 92459243Sobrien } 92559243Sobrien postcmd_active = 1; 92659243Sobrien if (!whyles && adrof1(STRpostcmd, &aliases)) 92759243Sobrien aliasrun(1, STRpostcmd, NULL); 92859243Sobrienleave: 92959243Sobrien postcmd_active = 0; 93059243Sobrien#ifdef BSDSIGS 93159243Sobrien (void) sigsetmask(omask); 93259243Sobrien#else /* !BSDSIGS */ 93359243Sobrien (void) sigrelse(SIGINT); 93459243Sobrien#endif /* BSDSIGS */ 93559243Sobrien} 93659243Sobrien 93759243Sobrien/* 93859243Sobrien * Paul Placeway 11/24/87 Added cwd_cmd by hacking precmd() into 93959243Sobrien * submission... Run every time $cwd is set (after it is set). Useful 94059243Sobrien * for putting your machine and cwd (or anything else) in an xterm title 94159243Sobrien * space. 94259243Sobrien */ 94359243Sobrienvoid 94459243Sobriencwd_cmd() 94559243Sobrien{ 94659243Sobrien#ifdef BSDSIGS 94759243Sobrien sigmask_t omask; 94859243Sobrien 94959243Sobrien omask = sigblock(sigmask(SIGINT)); 95059243Sobrien#else /* !BSDSIGS */ 95159243Sobrien (void) sighold(SIGINT); 95259243Sobrien#endif /* BSDSIGS */ 95359243Sobrien if (cwdcmd_active) { /* an error must have been caught */ 95459243Sobrien aliasrun(2, STRunalias, STRcwdcmd); 95559243Sobrien xprintf(CGETS(22, 4, "Faulty alias 'cwdcmd' removed.\n")); 95659243Sobrien goto leave; 95759243Sobrien } 95859243Sobrien cwdcmd_active = 1; 95959243Sobrien if (!whyles && adrof1(STRcwdcmd, &aliases)) 96059243Sobrien aliasrun(1, STRcwdcmd, NULL); 96159243Sobrienleave: 96259243Sobrien cwdcmd_active = 0; 96359243Sobrien#ifdef BSDSIGS 96459243Sobrien (void) sigsetmask(omask); 96559243Sobrien#else /* !BSDSIGS */ 96659243Sobrien (void) sigrelse(SIGINT); 96759243Sobrien#endif /* BSDSIGS */ 96859243Sobrien} 96959243Sobrien 97059243Sobrien/* 97159243Sobrien * Joachim Hoenig 07/16/91 Added beep_cmd, run every time tcsh wishes 97259243Sobrien * to beep the terminal bell. Useful for playing nice sounds instead. 97359243Sobrien */ 97459243Sobrienvoid 97559243Sobrienbeep_cmd() 97659243Sobrien{ 97759243Sobrien#ifdef BSDSIGS 97859243Sobrien sigmask_t omask; 97959243Sobrien 98059243Sobrien omask = sigblock(sigmask(SIGINT)); 98159243Sobrien#else /* !BSDSIGS */ 98259243Sobrien (void) sighold(SIGINT); 98359243Sobrien#endif /* BSDSIGS */ 98459243Sobrien if (beepcmd_active) { /* an error must have been caught */ 98559243Sobrien aliasrun(2, STRunalias, STRbeepcmd); 98659243Sobrien xprintf(CGETS(22, 5, "Faulty alias 'beepcmd' removed.\n")); 98759243Sobrien } 98859243Sobrien else { 98959243Sobrien beepcmd_active = 1; 99059243Sobrien if (!whyles && adrof1(STRbeepcmd, &aliases)) 99159243Sobrien aliasrun(1, STRbeepcmd, NULL); 99259243Sobrien } 99359243Sobrien beepcmd_active = 0; 99459243Sobrien#ifdef BSDSIGS 99559243Sobrien (void) sigsetmask(omask); 99659243Sobrien#else /* !BSDSIGS */ 99759243Sobrien (void) sigrelse(SIGINT); 99859243Sobrien#endif /* BSDSIGS */ 99959243Sobrien} 100059243Sobrien 100159243Sobrien 100259243Sobrien/* 100359243Sobrien * Karl Kleinpaste, 18 Jan 1984. 100459243Sobrien * Added period_cmd(), which executes the alias "periodic" every 100559243Sobrien * $tperiod minutes. Useful for occasional checking of msgs and such. 100659243Sobrien */ 100759243Sobrienvoid 100859243Sobrienperiod_cmd() 100959243Sobrien{ 101059243Sobrien register Char *vp; 101159243Sobrien time_t t, interval; 101259243Sobrien#ifdef BSDSIGS 101359243Sobrien sigmask_t omask; 101459243Sobrien 101559243Sobrien omask = sigblock(sigmask(SIGINT)); 101659243Sobrien#else /* !BSDSIGS */ 101759243Sobrien (void) sighold(SIGINT); 101859243Sobrien#endif /* BSDSIGS */ 101959243Sobrien if (periodic_active) { /* an error must have been caught */ 102059243Sobrien aliasrun(2, STRunalias, STRperiodic); 102159243Sobrien xprintf(CGETS(22, 6, "Faulty alias 'periodic' removed.\n")); 102259243Sobrien goto leave; 102359243Sobrien } 102459243Sobrien periodic_active = 1; 102559243Sobrien if (!whyles && adrof1(STRperiodic, &aliases)) { 102659243Sobrien vp = varval(STRtperiod); 102759243Sobrien if (vp == STRNULL) { 102859243Sobrien aliasrun(1, STRperiodic, NULL); 102959243Sobrien goto leave; 103059243Sobrien } 103159243Sobrien interval = getn(vp); 103259243Sobrien (void) time(&t); 103359243Sobrien if (t - t_period >= interval * 60) { 103459243Sobrien t_period = t; 103559243Sobrien aliasrun(1, STRperiodic, NULL); 103659243Sobrien } 103759243Sobrien } 103859243Sobrienleave: 103959243Sobrien periodic_active = 0; 104059243Sobrien#ifdef BSDSIGS 104159243Sobrien (void) sigsetmask(omask); 104259243Sobrien#else /* !BSDSIGS */ 104359243Sobrien (void) sigrelse(SIGINT); 104459243Sobrien#endif /* BSDSIGS */ 104559243Sobrien} 104659243Sobrien 104783098Smp 104883098Smp/* 104983098Smp * GrP Greg Parker May 2001 105083098Smp * Added job_cmd(), which is run every time a job is started or 105183098Smp * foregrounded. The command is passed a single argument, the string 105283098Smp * used to start the job originally. With precmd, useful for setting 105383098Smp * xterm titles. 105483098Smp * Cloned from cwd_cmd(). 105583098Smp */ 105683098Smpvoid 105783098Smpjob_cmd(args) 105883098Smp Char *args; 105983098Smp{ 106083098Smp#ifdef BSDSIGS 106183098Smp sigmask_t omask; 106283098Smp 106383098Smp omask = sigblock(sigmask(SIGINT)); 106483098Smp#else /* !BSDSIGS */ 106583098Smp (void) sighold(SIGINT); 106683098Smp#endif /* BSDSIGS */ 106783098Smp if (jobcmd_active) { /* an error must have been caught */ 106883098Smp aliasrun(2, STRunalias, STRjobcmd); 106983098Smp xprintf(CGETS(22, 14, "Faulty alias 'jobcmd' removed.\n")); 107083098Smp goto leave; 107183098Smp } 107283098Smp jobcmd_active = 1; 107383098Smp if (!whyles && adrof1(STRjobcmd, &aliases)) 107483098Smp aliasrun(2, STRjobcmd, args); 107583098Smpleave: 107683098Smp jobcmd_active = 0; 107783098Smp#ifdef BSDSIGS 107883098Smp (void) sigsetmask(omask); 107983098Smp#else /* !BSDSIGS */ 108083098Smp (void) sigrelse(SIGINT); 108183098Smp#endif /* BSDSIGS */ 108283098Smp} 108383098Smp 108483098Smp 108559243Sobrien/* 108659243Sobrien * Karl Kleinpaste, 21oct1983. 108759243Sobrien * Set up a one-word alias command, for use for special things. 108859243Sobrien * This code is based on the mainline of process(). 108959243Sobrien */ 109059243Sobrienvoid 109159243Sobrienaliasrun(cnt, s1, s2) 109259243Sobrien int cnt; 109359243Sobrien Char *s1, *s2; 109459243Sobrien{ 109559243Sobrien struct wordent w, *new1, *new2; /* for holding alias name */ 109659243Sobrien struct command *t = NULL; 109759243Sobrien jmp_buf_t osetexit; 109859243Sobrien int status; 109959243Sobrien 110059243Sobrien getexit(osetexit); 110159243Sobrien if (seterr) { 110259243Sobrien xfree((ptr_t) seterr); 110359243Sobrien seterr = NULL; /* don't repeatedly print err msg. */ 110459243Sobrien } 110559243Sobrien w.word = STRNULL; 110659243Sobrien new1 = (struct wordent *) xcalloc(1, sizeof w); 110759243Sobrien new1->word = Strsave(s1); 110859243Sobrien if (cnt == 1) { 110959243Sobrien /* build a lex list with one word. */ 111059243Sobrien w.next = w.prev = new1; 111159243Sobrien new1->next = new1->prev = &w; 111259243Sobrien } 111359243Sobrien else { 111459243Sobrien /* build a lex list with two words. */ 111559243Sobrien new2 = (struct wordent *) xcalloc(1, sizeof w); 111659243Sobrien new2->word = Strsave(s2); 111759243Sobrien w.next = new2->prev = new1; 111859243Sobrien new1->next = w.prev = new2; 111959243Sobrien new1->prev = new2->next = &w; 112059243Sobrien } 112159243Sobrien 112259243Sobrien /* Save the old status */ 112359243Sobrien status = getn(varval(STRstatus)); 112459243Sobrien 112559243Sobrien /* expand aliases like process() does. */ 112659243Sobrien alias(&w); 112759243Sobrien /* build a syntax tree for the command. */ 112859243Sobrien t = syntax(w.next, &w, 0); 112959243Sobrien if (seterr) 113059243Sobrien stderror(ERR_OLD); 113159243Sobrien 113259243Sobrien psavejob(); 113359243Sobrien 113459243Sobrien 113559243Sobrien /* catch any errors here */ 113659243Sobrien if (setexit() == 0) 113759243Sobrien /* execute the parse tree. */ 113859243Sobrien /* 113959243Sobrien * From: Michael Schroeder <mlschroe@immd4.informatik.uni-erlangen.de> 114059243Sobrien * was execute(t, tpgrp); 114159243Sobrien */ 114259243Sobrien execute(t, tpgrp > 0 ? tpgrp : -1, NULL, NULL); 114359243Sobrien /* done. free the lex list and parse tree. */ 114459243Sobrien freelex(&w), freesyn(t); 114559243Sobrien if (haderr) { 114659243Sobrien haderr = 0; 114759243Sobrien /* 114859243Sobrien * Either precmd, or cwdcmd, or periodic had an error. Call it again so 114959243Sobrien * that it is removed 115059243Sobrien */ 115159243Sobrien if (precmd_active) 115259243Sobrien precmd(); 115359243Sobrien if (postcmd_active) 115459243Sobrien postcmd(); 115559243Sobrien#ifdef notdef 115659243Sobrien /* 115759243Sobrien * XXX: On the other hand, just interrupting them causes an error too. 115859243Sobrien * So if we hit ^C in the middle of cwdcmd or periodic the alias gets 115959243Sobrien * removed. We don't want that. Note that we want to remove precmd 116059243Sobrien * though, cause that could lead into an infinite loop. This should be 116159243Sobrien * fixed correctly, but then haderr should give us the whole exit 116259243Sobrien * status not just true or false. 116359243Sobrien */ 116459243Sobrien else if (cwdcmd_active) 116559243Sobrien cwd_cmd(); 116659243Sobrien else if (beepcmd_active) 116759243Sobrien beep_cmd(); 116859243Sobrien else if (periodic_active) 116959243Sobrien period_cmd(); 117059243Sobrien#endif /* notdef */ 117159243Sobrien } 117259243Sobrien /* reset the error catcher to the old place */ 117359243Sobrien resexit(osetexit); 117459243Sobrien prestjob(); 117559243Sobrien pendjob(); 117659243Sobrien /* Restore status */ 117759243Sobrien set(STRstatus, putn(status), VAR_READWRITE); 117859243Sobrien} 117959243Sobrien 118059243Sobrienvoid 118159243Sobriensetalarm(lck) 118259243Sobrien int lck; 118359243Sobrien{ 118459243Sobrien struct varent *vp; 118559243Sobrien Char *cp; 118659243Sobrien unsigned alrm_time = 0, logout_time, lock_time; 118759243Sobrien time_t cl, nl, sched_dif; 118859243Sobrien 118959243Sobrien if ((vp = adrof(STRautologout)) != NULL) { 119059243Sobrien if ((cp = vp->vec[0]) != 0) { 119159243Sobrien if ((logout_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { 119259243Sobrien alrm_time = logout_time; 119359243Sobrien alm_fun = auto_logout; 119459243Sobrien } 119559243Sobrien } 119659243Sobrien if ((cp = vp->vec[1]) != 0) { 119759243Sobrien if ((lock_time = (unsigned) atoi(short2str(cp)) * 60) > 0) { 119859243Sobrien if (lck) { 119959243Sobrien if (alrm_time == 0 || lock_time < alrm_time) { 120059243Sobrien alrm_time = lock_time; 120159243Sobrien alm_fun = auto_lock; 120259243Sobrien } 120359243Sobrien } 120459243Sobrien else /* lock_time always < alrm_time */ 120559243Sobrien if (alrm_time) 120659243Sobrien alrm_time -= lock_time; 120759243Sobrien } 120859243Sobrien } 120959243Sobrien } 121059243Sobrien if ((nl = sched_next()) != -1) { 121159243Sobrien (void) time(&cl); 121259243Sobrien sched_dif = nl > cl ? nl - cl : 0; 121359243Sobrien if ((alrm_time == 0) || ((unsigned) sched_dif < alrm_time)) { 121459243Sobrien alrm_time = ((unsigned) sched_dif) + 1; 121559243Sobrien alm_fun = sched_run; 121659243Sobrien } 121759243Sobrien } 121859243Sobrien (void) alarm(alrm_time); /* Autologout ON */ 121959243Sobrien} 122059243Sobrien 122159243Sobrien#undef RMDEBUG /* For now... */ 122259243Sobrien 122359243Sobrienvoid 122459243Sobrienrmstar(cp) 122559243Sobrien struct wordent *cp; 122659243Sobrien{ 122759243Sobrien struct wordent *we, *args; 122859243Sobrien register struct wordent *tmp, *del; 122959243Sobrien 123059243Sobrien#ifdef RMDEBUG 123159243Sobrien static Char STRrmdebug[] = {'r', 'm', 'd', 'e', 'b', 'u', 'g', '\0'}; 123259243Sobrien Char *tag; 123359243Sobrien#endif /* RMDEBUG */ 123459243Sobrien Char *charac; 123559243Sobrien char c; 123659243Sobrien int ask, doit, star = 0, silent = 0; 123759243Sobrien 123859243Sobrien if (!adrof(STRrmstar)) 123959243Sobrien return; 124059243Sobrien#ifdef RMDEBUG 124159243Sobrien tag = varval(STRrmdebug); 124259243Sobrien#endif /* RMDEBUG */ 124359243Sobrien we = cp->next; 124459243Sobrien while (*we->word == ';' && we != cp) 124559243Sobrien we = we->next; 124659243Sobrien while (we != cp) { 124759243Sobrien#ifdef RMDEBUG 124859243Sobrien if (*tag) 124959243Sobrien xprintf(CGETS(22, 7, "parsing command line\n")); 125059243Sobrien#endif /* RMDEBUG */ 125159243Sobrien if (!Strcmp(we->word, STRrm)) { 125259243Sobrien args = we->next; 125359243Sobrien ask = (*args->word != '-'); 125459243Sobrien while (*args->word == '-' && !silent) { /* check options */ 125559243Sobrien for (charac = (args->word + 1); *charac && !silent; charac++) 125659243Sobrien silent = (*charac == 'i' || *charac == 'f'); 125759243Sobrien args = args->next; 125859243Sobrien } 125959243Sobrien ask = (ask || (!ask && !silent)); 126059243Sobrien if (ask) { 126159243Sobrien for (; !star && *args->word != ';' 126259243Sobrien && args != cp; args = args->next) 126359243Sobrien if (!Strcmp(args->word, STRstar)) 126459243Sobrien star = 1; 126559243Sobrien if (ask && star) { 126659243Sobrien xprintf(CGETS(22, 8, 126759243Sobrien "Do you really want to delete all files? [n/y] ")); 126859243Sobrien flush(); 126959243Sobrien (void) force_read(SHIN, &c, 1); 127059243Sobrien /* 127159243Sobrien * Perhaps we should use the yesexpr from the 127259243Sobrien * actual locale 127359243Sobrien */ 127459243Sobrien doit = (strchr(CGETS(22, 14, "Yy"), c) != NULL); 127559243Sobrien while (c != '\n' && force_read(SHIN, &c, 1) == 1) 127659243Sobrien continue; 127759243Sobrien if (!doit) { 127859243Sobrien /* remove the command instead */ 127959243Sobrien#ifdef RMDEBUG 128059243Sobrien if (*tag) 128159243Sobrien xprintf(CGETS(22, 9, 128259243Sobrien "skipping deletion of files!\n")); 128359243Sobrien#endif /* RMDEBUG */ 128459243Sobrien for (tmp = we; 128559243Sobrien *tmp->word != '\n' && 128659243Sobrien *tmp->word != ';' && tmp != cp;) { 128759243Sobrien tmp->prev->next = tmp->next; 128859243Sobrien tmp->next->prev = tmp->prev; 128959243Sobrien xfree((ptr_t) tmp->word); 129059243Sobrien del = tmp; 129159243Sobrien tmp = tmp->next; 129259243Sobrien xfree((ptr_t) del); 129359243Sobrien } 129459243Sobrien if (*tmp->word == ';') { 129559243Sobrien tmp->prev->next = tmp->next; 129659243Sobrien tmp->next->prev = tmp->prev; 129759243Sobrien xfree((ptr_t) tmp->word); 129859243Sobrien del = tmp; 129983098Smp tmp = tmp->next; 130059243Sobrien xfree((ptr_t) del); 130159243Sobrien } 130283098Smp we = tmp; 130383098Smp continue; 130459243Sobrien } 130559243Sobrien } 130659243Sobrien } 130759243Sobrien } 130859243Sobrien for (we = we->next; 130959243Sobrien *we->word != ';' && we != cp; 131059243Sobrien we = we->next) 131159243Sobrien continue; 131259243Sobrien if (*we->word == ';') 131359243Sobrien we = we->next; 131459243Sobrien } 131559243Sobrien#ifdef RMDEBUG 131659243Sobrien if (*tag) { 131759243Sobrien xprintf(CGETS(22, 10, "command line now is:\n")); 131859243Sobrien for (we = cp->next; we != cp; we = we->next) 131959243Sobrien xprintf("%S ", we->word); 132059243Sobrien } 132159243Sobrien#endif /* RMDEBUG */ 132259243Sobrien return; 132359243Sobrien} 132459243Sobrien 132559243Sobrien#ifdef BSDJOBS 132659243Sobrien/* Check if command is in continue list 132759243Sobrien and do a "aliasing" if it exists as a job in background */ 132859243Sobrien 132959243Sobrien#undef CNDEBUG /* For now */ 133059243Sobrienvoid 133159243Sobriencontinue_jobs(cp) 133259243Sobrien struct wordent *cp; 133359243Sobrien{ 133459243Sobrien struct wordent *we; 133559243Sobrien register struct process *pp, *np; 133659243Sobrien Char *cmd, *continue_list, *continue_args_list; 133759243Sobrien 133859243Sobrien#ifdef CNDEBUG 133959243Sobrien Char *tag; 134059243Sobrien static Char STRcndebug[] = 134159243Sobrien {'c', 'n', 'd', 'e', 'b', 'u', 'g', '\0'}; 134259243Sobrien#endif /* CNDEBUG */ 134359243Sobrien bool in_cont_list, in_cont_arg_list; 134459243Sobrien 134559243Sobrien 134659243Sobrien#ifdef CNDEBUG 134759243Sobrien tag = varval(STRcndebug); 134859243Sobrien#endif /* CNDEBUG */ 134959243Sobrien continue_list = varval(STRcontinue); 135059243Sobrien continue_args_list = varval(STRcontinue_args); 135159243Sobrien if (*continue_list == '\0' && *continue_args_list == '\0') 135259243Sobrien return; 135359243Sobrien 135459243Sobrien we = cp->next; 135559243Sobrien while (*we->word == ';' && we != cp) 135659243Sobrien we = we->next; 135759243Sobrien while (we != cp) { 135859243Sobrien#ifdef CNDEBUG 135959243Sobrien if (*tag) 136059243Sobrien xprintf(CGETS(22, 11, "parsing command line\n")); 136159243Sobrien#endif /* CNDEBUG */ 136259243Sobrien cmd = we->word; 136359243Sobrien in_cont_list = inlist(continue_list, cmd); 136459243Sobrien in_cont_arg_list = inlist(continue_args_list, cmd); 136559243Sobrien if (in_cont_list || in_cont_arg_list) { 136659243Sobrien#ifdef CNDEBUG 136759243Sobrien if (*tag) 136859243Sobrien xprintf(CGETS(22, 12, "in one of the lists\n")); 136959243Sobrien#endif /* CNDEBUG */ 137059243Sobrien np = NULL; 137159243Sobrien for (pp = proclist.p_next; pp; pp = pp->p_next) { 137259243Sobrien if (prefix(cmd, pp->p_command)) { 137359243Sobrien if (pp->p_index) { 137459243Sobrien np = pp; 137559243Sobrien break; 137659243Sobrien } 137759243Sobrien } 137859243Sobrien } 137959243Sobrien if (np) { 138059243Sobrien insert(we, in_cont_arg_list); 138159243Sobrien } 138259243Sobrien } 138359243Sobrien for (we = we->next; 138459243Sobrien *we->word != ';' && we != cp; 138559243Sobrien we = we->next) 138659243Sobrien continue; 138759243Sobrien if (*we->word == ';') 138859243Sobrien we = we->next; 138959243Sobrien } 139059243Sobrien#ifdef CNDEBUG 139159243Sobrien if (*tag) { 139259243Sobrien xprintf(CGETS(22, 13, "command line now is:\n")); 139359243Sobrien for (we = cp->next; we != cp; we = we->next) 139459243Sobrien xprintf("%S ", we->word); 139559243Sobrien } 139659243Sobrien#endif /* CNDEBUG */ 139759243Sobrien return; 139859243Sobrien} 139959243Sobrien 140059243Sobrien/* The actual "aliasing" of for backgrounds() is done here 140159243Sobrien with the aid of insert_we(). */ 140259243Sobrienstatic void 140359243Sobrieninsert(pl, file_args) 140459243Sobrien struct wordent *pl; 140559243Sobrien bool file_args; 140659243Sobrien{ 140759243Sobrien struct wordent *now, *last; 140859243Sobrien Char *cmd, *bcmd, *cp1, *cp2; 140959243Sobrien int cmd_len; 141059243Sobrien Char *pause = STRunderpause; 141159243Sobrien int p_len = (int) Strlen(pause); 141259243Sobrien 141359243Sobrien cmd_len = (int) Strlen(pl->word); 141459243Sobrien cmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 1) * sizeof(Char))); 141559243Sobrien (void) Strcpy(cmd, pl->word); 141659243Sobrien/* Do insertions at beginning, first replace command word */ 141759243Sobrien 141859243Sobrien if (file_args) { 141959243Sobrien now = pl; 142059243Sobrien xfree((ptr_t) now->word); 142159243Sobrien now->word = (Char *) xcalloc(1, (size_t) (5 * sizeof(Char))); 142259243Sobrien (void) Strcpy(now->word, STRecho); 142359243Sobrien 142459243Sobrien now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); 142559243Sobrien now->word = (Char *) xcalloc(1, (size_t) (6 * sizeof(Char))); 142659243Sobrien (void) Strcpy(now->word, STRbackqpwd); 142759243Sobrien insert_we(now, pl); 142859243Sobrien 142959243Sobrien for (last = now; *last->word != '\n' && *last->word != ';'; 143059243Sobrien last = last->next) 143159243Sobrien continue; 143259243Sobrien 143359243Sobrien now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); 143459243Sobrien now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); 143559243Sobrien (void) Strcpy(now->word, STRgt); 143659243Sobrien insert_we(now, last->prev); 143759243Sobrien 143859243Sobrien now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); 143959243Sobrien now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); 144059243Sobrien (void) Strcpy(now->word, STRbang); 144159243Sobrien insert_we(now, last->prev); 144259243Sobrien 144359243Sobrien now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); 144459243Sobrien now->word = (Char *) xcalloc(1, (size_t) cmd_len + p_len + 4); 144559243Sobrien cp1 = now->word; 144659243Sobrien cp2 = cmd; 144759243Sobrien *cp1++ = '~'; 144859243Sobrien *cp1++ = '/'; 144959243Sobrien *cp1++ = '.'; 145059243Sobrien while ((*cp1++ = *cp2++) != '\0') 145159243Sobrien continue; 145259243Sobrien cp1--; 145359243Sobrien cp2 = pause; 145459243Sobrien while ((*cp1++ = *cp2++) != '\0') 145559243Sobrien continue; 145659243Sobrien insert_we(now, last->prev); 145759243Sobrien 145859243Sobrien now = (struct wordent *) xcalloc(1, (size_t) sizeof(struct wordent)); 145959243Sobrien now->word = (Char *) xcalloc(1, (size_t) (2 * sizeof(Char))); 146059243Sobrien (void) Strcpy(now->word, STRsemi); 146159243Sobrien insert_we(now, last->prev); 146259243Sobrien bcmd = (Char *) xcalloc(1, (size_t) ((cmd_len + 2) * sizeof(Char))); 146359243Sobrien cp1 = bcmd; 146459243Sobrien cp2 = cmd; 146559243Sobrien *cp1++ = '%'; 146659243Sobrien while ((*cp1++ = *cp2++) != '\0') 146759243Sobrien continue; 146859243Sobrien now = (struct wordent *) xcalloc(1, (size_t) (sizeof(struct wordent))); 146959243Sobrien now->word = bcmd; 147059243Sobrien insert_we(now, last->prev); 147159243Sobrien } 147259243Sobrien else { 147359243Sobrien struct wordent *del; 147459243Sobrien 147559243Sobrien now = pl; 147659243Sobrien xfree((ptr_t) now->word); 147759243Sobrien now->word = (Char *) xcalloc(1, 147859243Sobrien (size_t) ((cmd_len + 2) * sizeof(Char))); 147959243Sobrien cp1 = now->word; 148059243Sobrien cp2 = cmd; 148159243Sobrien *cp1++ = '%'; 148259243Sobrien while ((*cp1++ = *cp2++) != '\0') 148359243Sobrien continue; 148459243Sobrien for (now = now->next; 148559243Sobrien *now->word != '\n' && *now->word != ';' && now != pl;) { 148659243Sobrien now->prev->next = now->next; 148759243Sobrien now->next->prev = now->prev; 148859243Sobrien xfree((ptr_t) now->word); 148959243Sobrien del = now; 149059243Sobrien now = now->next; 149159243Sobrien xfree((ptr_t) del); 149259243Sobrien } 149359243Sobrien } 149459243Sobrien} 149559243Sobrien 149659243Sobrienstatic void 149759243Sobrieninsert_we(new, where) 149859243Sobrien struct wordent *new, *where; 149959243Sobrien{ 150059243Sobrien 150159243Sobrien new->prev = where; 150259243Sobrien new->next = where->next; 150359243Sobrien where->next = new; 150459243Sobrien new->next->prev = new; 150559243Sobrien} 150659243Sobrien 150759243Sobrienstatic int 150859243Sobrieninlist(list, name) 150959243Sobrien Char *list, *name; 151059243Sobrien{ 151159243Sobrien register Char *l, *n; 151259243Sobrien 151359243Sobrien l = list; 151459243Sobrien n = name; 151559243Sobrien 151659243Sobrien while (*l && *n) { 151759243Sobrien if (*l == *n) { 151859243Sobrien l++; 151959243Sobrien n++; 152059243Sobrien if (*n == '\0' && (*l == ' ' || *l == '\0')) 152159243Sobrien return (1); 152259243Sobrien else 152359243Sobrien continue; 152459243Sobrien } 152559243Sobrien else { 152659243Sobrien while (*l && *l != ' ') 152759243Sobrien l++; /* skip to blank */ 152859243Sobrien while (*l && *l == ' ') 152959243Sobrien l++; /* and find first nonblank character */ 153059243Sobrien n = name; 153159243Sobrien } 153259243Sobrien } 153359243Sobrien return (0); 153459243Sobrien} 153559243Sobrien 153659243Sobrien#endif /* BSDJOBS */ 153759243Sobrien 153859243Sobrien 153959243Sobrien/* 154059243Sobrien * Implement a small cache for tilde names. This is used primarily 154159243Sobrien * to expand tilde names to directories, but also 154259243Sobrien * we can find users from their home directories for the tilde 154359243Sobrien * prompt, on machines where yp lookup is slow this can be a big win... 154459243Sobrien * As with any cache this can run out of sync, rehash can sync it again. 154559243Sobrien */ 154659243Sobrienstatic struct tildecache { 154759243Sobrien Char *user; 154859243Sobrien Char *home; 154959243Sobrien int hlen; 155059243Sobrien} *tcache = NULL; 155159243Sobrien 155259243Sobrien#define TILINCR 10 155359243Sobrienint tlength = 0; 155459243Sobrienstatic int tsize = TILINCR; 155559243Sobrien 155659243Sobrienstatic int 155759243Sobrientildecompare(p1, p2) 155859243Sobrien struct tildecache *p1, *p2; 155959243Sobrien{ 156059243Sobrien return Strcmp(p1->user, p2->user); 156159243Sobrien} 156259243Sobrien 156359243Sobrienstatic Char * 156459243Sobriengethomedir(us) 156559243Sobrien Char *us; 156659243Sobrien{ 156759243Sobrien register struct passwd *pp; 156859243Sobrien#ifdef HESIOD 156959243Sobrien char **res, **res1, *cp; 157059243Sobrien Char *rp; 157159243Sobrien#endif /* HESIOD */ 157259243Sobrien 157359243Sobrien pp = getpwnam(short2str(us)); 157459243Sobrien#ifdef YPBUGS 157559243Sobrien fix_yp_bugs(); 157659243Sobrien#endif /* YPBUGS */ 157783098Smp if (pp != NULL) { 157883098Smp /* Don't return if root */ 157983098Smp if (pp->pw_dir[0] == '/' && pp->pw_dir[1] == '\0') 158083098Smp return NULL; 158183098Smp else 158283098Smp return Strsave(str2short(pp->pw_dir)); 158383098Smp } 158459243Sobrien#ifdef HESIOD 158559243Sobrien res = hes_resolve(short2str(us), "filsys"); 158683098Smp rp = NULL; 158783098Smp if (res != NULL) { 158883098Smp if ((*res) != NULL) { 158959243Sobrien /* 159059243Sobrien * Look at the first token to determine how to interpret 159159243Sobrien * the rest of it. 159259243Sobrien * Yes, strtok is evil (it's not thread-safe), but it's also 159359243Sobrien * easy to use. 159459243Sobrien */ 159559243Sobrien cp = strtok(*res, " "); 159659243Sobrien if (strcmp(cp, "AFS") == 0) { 159759243Sobrien /* next token is AFS pathname.. */ 159859243Sobrien cp = strtok(NULL, " "); 159959243Sobrien if (cp != NULL) 160059243Sobrien rp = Strsave(str2short(cp)); 160159243Sobrien } else if (strcmp(cp, "NFS") == 0) { 160259243Sobrien cp = NULL; 160359243Sobrien if ((strtok(NULL, " ")) && /* skip remote pathname */ 160459243Sobrien (strtok(NULL, " ")) && /* skip host */ 160559243Sobrien (strtok(NULL, " ")) && /* skip mode */ 160659243Sobrien (cp = strtok(NULL, " "))) { 160759243Sobrien rp = Strsave(str2short(cp)); 160859243Sobrien } 160959243Sobrien } 161059243Sobrien } 161159243Sobrien for (res1 = res; *res1; res1++) 161259243Sobrien free(*res1); 161383098Smp if (rp != NULL && rp[0] == '/' && rp[1] == '\0') { 161483098Smp xfree((ptr_t)rp); 161583098Smp rp = NULL; 161683098Smp } 161759243Sobrien return rp; 161859243Sobrien } 161959243Sobrien#endif /* HESIOD */ 162059243Sobrien return NULL; 162159243Sobrien} 162259243Sobrien 162359243SobrienChar * 162459243Sobriengettilde(us) 162559243Sobrien Char *us; 162659243Sobrien{ 162759243Sobrien struct tildecache *bp1, *bp2, *bp; 162859243Sobrien Char *hd; 162959243Sobrien 163059243Sobrien /* Ignore NIS special names */ 163159243Sobrien if (*us == '+' || *us == '-') 163259243Sobrien return NULL; 163359243Sobrien 163459243Sobrien if (tcache == NULL) 163559243Sobrien tcache = (struct tildecache *) xmalloc((size_t) (TILINCR * 163659243Sobrien sizeof(struct tildecache))); 163759243Sobrien /* 163859243Sobrien * Binary search 163959243Sobrien */ 164059243Sobrien for (bp1 = tcache, bp2 = tcache + tlength; bp1 < bp2;) { 164159243Sobrien register int i; 164259243Sobrien 164359243Sobrien bp = bp1 + ((bp2 - bp1) >> 1); 164459243Sobrien if ((i = *us - *bp->user) == 0 && (i = Strcmp(us, bp->user)) == 0) 164559243Sobrien return (bp->home); 164659243Sobrien if (i < 0) 164759243Sobrien bp2 = bp; 164859243Sobrien else 164959243Sobrien bp1 = bp + 1; 165059243Sobrien } 165159243Sobrien /* 165259243Sobrien * Not in the cache, try to get it from the passwd file 165359243Sobrien */ 165459243Sobrien hd = gethomedir(us); 165559243Sobrien if (hd == NULL) 165659243Sobrien return NULL; 165759243Sobrien 165859243Sobrien /* 165959243Sobrien * Update the cache 166059243Sobrien */ 166159243Sobrien tcache[tlength].user = Strsave(us); 166259243Sobrien tcache[tlength].home = hd; 166359243Sobrien tcache[tlength++].hlen = (int) Strlen(hd); 166459243Sobrien 166559243Sobrien qsort((ptr_t) tcache, (size_t) tlength, sizeof(struct tildecache), 166659243Sobrien (int (*) __P((const void *, const void *))) tildecompare); 166759243Sobrien 166859243Sobrien if (tlength == tsize) { 166959243Sobrien tsize += TILINCR; 167059243Sobrien tcache = (struct tildecache *) xrealloc((ptr_t) tcache, 167159243Sobrien (size_t) (tsize * 167259243Sobrien sizeof(struct tildecache))); 167359243Sobrien } 167459243Sobrien return (hd); 167559243Sobrien} 167659243Sobrien 167759243Sobrien/* 167859243Sobrien * Return the username if the directory path passed contains a 167959243Sobrien * user's home directory in the tilde cache, otherwise return NULL 168059243Sobrien * hm points to the place where the path became different. 168159243Sobrien * Special case: Our own home directory. 168259243Sobrien * If we are passed a null pointer, then we flush the cache. 168359243Sobrien */ 168459243SobrienChar * 168559243Sobriengetusername(hm) 168659243Sobrien Char **hm; 168759243Sobrien{ 168859243Sobrien Char *h, *p; 168959243Sobrien int i, j; 169059243Sobrien 169159243Sobrien if (hm == NULL) { 169259243Sobrien for (i = 0; i < tlength; i++) { 169359243Sobrien xfree((ptr_t) tcache[i].home); 169459243Sobrien xfree((ptr_t) tcache[i].user); 169559243Sobrien } 169659243Sobrien xfree((ptr_t) tcache); 169759243Sobrien tlength = 0; 169859243Sobrien tsize = TILINCR; 169959243Sobrien tcache = NULL; 170059243Sobrien return NULL; 170159243Sobrien } 170259243Sobrien if (((h = varval(STRhome)) != STRNULL) && 170359243Sobrien (Strncmp(p = *hm, h, (size_t) (j = (int) Strlen(h))) == 0) && 170459243Sobrien (p[j] == '/' || p[j] == '\0')) { 170559243Sobrien *hm = &p[j]; 170659243Sobrien return STRNULL; 170759243Sobrien } 170859243Sobrien for (i = 0; i < tlength; i++) 170959243Sobrien if ((Strncmp(p = *hm, tcache[i].home, (size_t) 171059243Sobrien (j = tcache[i].hlen)) == 0) && (p[j] == '/' || p[j] == '\0')) { 171159243Sobrien *hm = &p[j]; 171259243Sobrien return tcache[i].user; 171359243Sobrien } 171459243Sobrien return NULL; 171559243Sobrien} 171659243Sobrien 171759243Sobrien#ifdef OBSOLETE 171859243Sobrien/* 171959243Sobrien * PWP: read a bunch of aliases out of a file QUICKLY. The format 172059243Sobrien * is almost the same as the result of saying "alias > FILE", except 172159243Sobrien * that saying "aliases > FILE" does not expand non-letters to printable 172259243Sobrien * sequences. 172359243Sobrien */ 172459243Sobrien/*ARGSUSED*/ 172559243Sobrienvoid 172659243Sobriendoaliases(v, c) 172759243Sobrien Char **v; 172859243Sobrien struct command *c; 172959243Sobrien{ 173059243Sobrien jmp_buf_t oldexit; 173159243Sobrien Char **vec, *lp; 173259243Sobrien int fd; 173359243Sobrien Char buf[BUFSIZE], line[BUFSIZE]; 173459243Sobrien char tbuf[BUFSIZE + 1], *tmp; 173559243Sobrien extern bool output_raw; /* PWP: in sh.print.c */ 173659243Sobrien 173759243Sobrien USE(c); 173859243Sobrien v++; 173959243Sobrien if (*v == 0) { 174059243Sobrien output_raw = 1; 174159243Sobrien plist(&aliases, VAR_ALL); 174259243Sobrien output_raw = 0; 174359243Sobrien return; 174459243Sobrien } 174559243Sobrien 174659243Sobrien gflag = 0, tglob(v); 174759243Sobrien if (gflag) { 174859243Sobrien v = globall(v); 174959243Sobrien if (v == 0) 175059243Sobrien stderror(ERR_NAME | ERR_NOMATCH); 175159243Sobrien } 175259243Sobrien else { 175359243Sobrien v = gargv = saveblk(v); 175459243Sobrien trim(v); 175559243Sobrien } 175659243Sobrien 175759243Sobrien if ((fd = open(tmp = short2str(*v), O_RDONLY)) < 0) 175859243Sobrien stderror(ERR_NAME | ERR_SYSTEM, tmp, strerror(errno)); 175959243Sobrien 176059243Sobrien getexit(oldexit); 176159243Sobrien if (setexit() == 0) { 176259243Sobrien for (;;) { 176359243Sobrien Char *p = NULL; 176459243Sobrien int n = 0; 176559243Sobrien lp = line; 176659243Sobrien for (;;) { 176759243Sobrien if (n <= 0) { 176859243Sobrien int i; 176959243Sobrien 177059243Sobrien if ((n = read(fd, tbuf, BUFSIZE)) <= 0) { 177159243Sobrien#ifdef convex 177259243Sobrien stderror(ERR_SYSTEM, progname, strerror(errno)); 177359243Sobrien#endif /* convex */ 177459243Sobrien goto eof; 177559243Sobrien } 177659243Sobrien for (i = 0; i < n; i++) 177759243Sobrien buf[i] = (Char) tbuf[i]; 177859243Sobrien p = buf; 177959243Sobrien } 178059243Sobrien n--; 178159243Sobrien if ((*lp++ = *p++) == '\n') { 178259243Sobrien lp[-1] = '\0'; 178359243Sobrien break; 178459243Sobrien } 178559243Sobrien } 178659243Sobrien for (lp = line; *lp; lp++) { 178759243Sobrien if (isspc(*lp)) { 178859243Sobrien *lp++ = '\0'; 178959243Sobrien while (isspc(*lp)) 179059243Sobrien lp++; 179159243Sobrien vec = (Char **) xmalloc((size_t) 179259243Sobrien (2 * sizeof(Char **))); 179359243Sobrien vec[0] = Strsave(lp); 179459243Sobrien vec[1] = NULL; 179559243Sobrien setq(strip(line), vec, &aliases, VAR_READWRITE); 179659243Sobrien break; 179759243Sobrien } 179859243Sobrien } 179959243Sobrien } 180059243Sobrien } 180159243Sobrien 180259243Sobrieneof: 180359243Sobrien (void) close(fd); 180459243Sobrien tw_cmd_free(); 180559243Sobrien if (gargv) 180659243Sobrien blkfree(gargv), gargv = 0; 180759243Sobrien resexit(oldexit); 180859243Sobrien} 180959243Sobrien#endif /* OBSOLETE */ 181059243Sobrien 181159243Sobrien 181259243Sobrien/* 181359243Sobrien * set the shell-level var to 1 or apply change to it. 181459243Sobrien */ 181559243Sobrienvoid 181659243Sobrienshlvl(val) 181759243Sobrien int val; 181859243Sobrien{ 181959243Sobrien char *cp; 182059243Sobrien 182159243Sobrien if ((cp = getenv("SHLVL")) != NULL) { 182259243Sobrien 182359243Sobrien if (loginsh) 182459243Sobrien val = 1; 182559243Sobrien else 182659243Sobrien val += atoi(cp); 182759243Sobrien 182859243Sobrien if (val <= 0) { 182959243Sobrien if (adrof(STRshlvl) != NULL) 183059243Sobrien unsetv(STRshlvl); 183159243Sobrien Unsetenv(STRKSHLVL); 183259243Sobrien } 183359243Sobrien else { 183459243Sobrien Char buff[BUFSIZE]; 183559243Sobrien 183659243Sobrien (void) Itoa(val, buff, 0, 0); 183759243Sobrien set(STRshlvl, Strsave(buff), VAR_READWRITE); 183859243Sobrien tsetenv(STRKSHLVL, buff); 183959243Sobrien } 184059243Sobrien } 184159243Sobrien else { 184259243Sobrien set(STRshlvl, SAVE("1"), VAR_READWRITE); 184359243Sobrien tsetenv(STRKSHLVL, str2short("1")); 184459243Sobrien } 184559243Sobrien} 184659243Sobrien 184759243Sobrien 184859243Sobrien/* fixio(): 184959243Sobrien * Try to recover from a read error 185059243Sobrien */ 185159243Sobrienint 185259243Sobrienfixio(fd, e) 185359243Sobrien int fd, e; 185459243Sobrien{ 185559243Sobrien switch (e) { 185659243Sobrien case -1: /* Make sure that the code is reachable */ 185759243Sobrien 185859243Sobrien#ifdef EWOULDBLOCK 185959243Sobrien case EWOULDBLOCK: 186059243Sobrien# define FDRETRY 186159243Sobrien#endif /* EWOULDBLOCK */ 186259243Sobrien 186359243Sobrien#if defined(POSIX) && defined(EAGAIN) 186459243Sobrien# if !defined(EWOULDBLOCK) || EWOULDBLOCK != EAGAIN 186559243Sobrien case EAGAIN: 186659243Sobrien# define FDRETRY 186759243Sobrien# endif /* !EWOULDBLOCK || EWOULDBLOCK != EAGAIN */ 186859243Sobrien#endif /* POSIX && EAGAIN */ 186959243Sobrien 187059243Sobrien e = 0; 187159243Sobrien#ifdef FDRETRY 187259243Sobrien# ifdef F_SETFL 187359243Sobrien/* 187459243Sobrien * Great! we have on suns 3 flavors and 5 names... 187559243Sobrien * I hope that will cover everything. 187659243Sobrien * I added some more defines... many systems have different defines. 187759243Sobrien * Rather than dealing with getting the right includes, we'll just 187859243Sobrien * cover all the known possibilities here. -- sterling@netcom.com 187959243Sobrien */ 188059243Sobrien# ifndef O_NONBLOCK 188159243Sobrien# define O_NONBLOCK 0 188259243Sobrien# endif /* O_NONBLOCK */ 188359243Sobrien# ifndef O_NDELAY 188459243Sobrien# define O_NDELAY 0 188559243Sobrien# endif /* O_NDELAY */ 188659243Sobrien# ifndef FNBIO 188759243Sobrien# define FNBIO 0 188859243Sobrien# endif /* FNBIO */ 188959243Sobrien# ifndef _FNBIO 189059243Sobrien# define _FNBIO 0 189159243Sobrien# endif /* _FNBIO */ 189259243Sobrien# ifndef FNONBIO 189359243Sobrien# define FNONBIO 0 189459243Sobrien# endif /* FNONBIO */ 189559243Sobrien# ifndef FNONBLOCK 189659243Sobrien# define FNONBLOCK 0 189759243Sobrien# endif /* FNONBLOCK */ 189859243Sobrien# ifndef _FNONBLOCK 189959243Sobrien# define _FNONBLOCK 0 190059243Sobrien# endif /* _FNONBLOCK */ 190159243Sobrien# ifndef FNDELAY 190259243Sobrien# define FNDELAY 0 190359243Sobrien# endif /* FNDELAY */ 190459243Sobrien# ifndef _FNDELAY 190559243Sobrien# define _FNDELAY 0 190659243Sobrien# endif /* _FNDELAY */ 190759243Sobrien# ifndef FNDLEAY /* Some linux versions have this typo */ 190859243Sobrien# define FNDLEAY 0 190959243Sobrien# endif /* FNDLEAY */ 191059243Sobrien if ((e = fcntl(fd, F_GETFL, 0)) == -1) 191159243Sobrien return -1; 191259243Sobrien 191359243Sobrien e &= ~(O_NDELAY|O_NONBLOCK|FNBIO|_FNBIO|FNONBIO|FNONBLOCK|_FNONBLOCK| 191459243Sobrien FNDELAY|_FNDELAY|FNDLEAY); /* whew! */ 191559243Sobrien if (fcntl(fd, F_SETFL, e) == -1) 191659243Sobrien return -1; 191759243Sobrien else 191859243Sobrien e = 1; 191959243Sobrien# endif /* F_SETFL */ 192059243Sobrien 192159243Sobrien# ifdef FIONBIO 192259243Sobrien e = 0; 192359243Sobrien if (ioctl(fd, FIONBIO, (ioctl_t) &e) == -1) 192459243Sobrien return -1; 192559243Sobrien else 192659243Sobrien e = 1; 192759243Sobrien# endif /* FIONBIO */ 192859243Sobrien 192959243Sobrien#endif /* FDRETRY */ 193059243Sobrien return e ? 0 : -1; 193159243Sobrien 193259243Sobrien case EINTR: 193359243Sobrien return 0; 193459243Sobrien 193559243Sobrien default: 193659243Sobrien return -1; 193759243Sobrien } 193859243Sobrien} 193959243Sobrien 194059243Sobrien/* collate(): 194159243Sobrien * String collation 194259243Sobrien */ 194359243Sobrienint 194459243Sobriencollate(a, b) 194559243Sobrien const Char *a; 194659243Sobrien const Char *b; 194759243Sobrien{ 194859243Sobrien int rv; 194959243Sobrien#ifdef SHORT_STRINGS 195059243Sobrien /* This strips the quote bit as a side effect */ 195159243Sobrien char *sa = strsave(short2str(a)); 195259243Sobrien char *sb = strsave(short2str(b)); 195359243Sobrien#else 195459243Sobrien char *sa = strip(strsave(a)); 195559243Sobrien char *sb = strip(strsave(b)); 195659243Sobrien#endif /* SHORT_STRINGS */ 195759243Sobrien 195859243Sobrien#if defined(NLS) && !defined(NOSTRCOLL) 195959243Sobrien errno = 0; /* strcoll sets errno, another brain-damage */ 196059243Sobrien 196159243Sobrien rv = strcoll(sa, sb); 196259243Sobrien 196359243Sobrien /* 196459243Sobrien * We should be checking for errno != 0, but some systems 196559243Sobrien * forget to reset errno to 0. So we only check for the 196659243Sobrien * only documented valid errno value for strcoll [EINVAL] 196759243Sobrien */ 196859243Sobrien if (errno == EINVAL) { 196959243Sobrien xfree((ptr_t) sa); 197059243Sobrien xfree((ptr_t) sb); 197159243Sobrien stderror(ERR_SYSTEM, "strcoll", strerror(errno)); 197259243Sobrien } 197359243Sobrien#else 197459243Sobrien rv = strcmp(sa, sb); 197559243Sobrien#endif /* NLS && !NOSTRCOLL */ 197659243Sobrien 197759243Sobrien xfree((ptr_t) sa); 197859243Sobrien xfree((ptr_t) sb); 197959243Sobrien 198059243Sobrien return rv; 198159243Sobrien} 198259243Sobrien 198359243Sobrien#ifdef HASHBANG 198459243Sobrien/* 198559243Sobrien * From: peter@zeus.dialix.oz.au (Peter Wemm) 198659243Sobrien * If exec() fails look first for a #! [word] [word] .... 198759243Sobrien * If it is, splice the header into the argument list and retry. 198859243Sobrien */ 198959243Sobrien#define HACKBUFSZ 1024 /* Max chars in #! vector */ 199059243Sobrien#define HACKVECSZ 128 /* Max words in #! vector */ 199159243Sobrienint 199259243Sobrienhashbang(fd, vp) 199359243Sobrien int fd; 199459243Sobrien Char ***vp; 199559243Sobrien{ 199659243Sobrien unsigned char lbuf[HACKBUFSZ]; 199759243Sobrien char *sargv[HACKVECSZ]; 199859243Sobrien unsigned char *p, *ws; 199959243Sobrien int sargc = 0; 200069408Sache#ifdef WINNT_NATIVE 200159243Sobrien int fw = 0; /* found at least one word */ 200259243Sobrien int first_word = 0; 200369408Sache#endif /* WINNT_NATIVE */ 200459243Sobrien 200559243Sobrien if (read(fd, (char *) lbuf, HACKBUFSZ) <= 0) 200659243Sobrien return -1; 200759243Sobrien 200859243Sobrien ws = 0; /* word started = 0 */ 200959243Sobrien 201059243Sobrien for (p = lbuf; p < &lbuf[HACKBUFSZ]; ) 201159243Sobrien switch (*p) { 201259243Sobrien case ' ': 201359243Sobrien case '\t': 201469408Sache#ifdef WINNT_NATIVE 201559243Sobrien case '\r': 201669408Sache#endif /* WINNT_NATIVE */ 201759243Sobrien if (ws) { /* a blank after a word.. save it */ 201859243Sobrien *p = '\0'; 201969408Sache#ifndef WINNT_NATIVE 202059243Sobrien if (sargc < HACKVECSZ - 1) 202159243Sobrien sargv[sargc++] = ws; 202259243Sobrien ws = NULL; 202369408Sache#else /* WINNT_NATIVE */ 202459243Sobrien if (sargc < HACKVECSZ - 1) { 202559243Sobrien sargv[sargc] = first_word ? NULL: hb_subst(ws); 202659243Sobrien if (sargv[sargc] == NULL) 202759243Sobrien sargv[sargc] = ws; 202859243Sobrien sargc++; 202959243Sobrien } 203059243Sobrien ws = NULL; 203159243Sobrien fw = 1; 203259243Sobrien first_word = 1; 203369408Sache#endif /* WINNT_NATIVE */ 203459243Sobrien } 203559243Sobrien p++; 203659243Sobrien continue; 203759243Sobrien 203859243Sobrien case '\0': /* Whoa!! what the hell happened */ 203959243Sobrien return -1; 204059243Sobrien 204159243Sobrien case '\n': /* The end of the line. */ 204259243Sobrien if ( 204369408Sache#ifdef WINNT_NATIVE 204459243Sobrien fw || 204569408Sache#endif /* WINNT_NATIVE */ 204659243Sobrien ws) { /* terminate the last word */ 204759243Sobrien *p = '\0'; 204869408Sache#ifndef WINNT_NATIVE 204959243Sobrien if (sargc < HACKVECSZ - 1) 205059243Sobrien sargv[sargc++] = ws; 205169408Sache#else /* WINNT_NATIVE */ 205259243Sobrien if (sargc < HACKVECSZ - 1) { /* deal with the 1-word case */ 205359243Sobrien sargv[sargc] = first_word? NULL : hb_subst(ws); 205459243Sobrien if (sargv[sargc] == NULL) 205559243Sobrien sargv[sargc] = ws; 205659243Sobrien sargc++; 205759243Sobrien } 205869408Sache#endif /* !WINNT_NATIVE */ 205959243Sobrien } 206059243Sobrien sargv[sargc] = NULL; 206159243Sobrien ws = NULL; 206259243Sobrien if (sargc > 0) { 206359243Sobrien *vp = blk2short(sargv); 206459243Sobrien return 0; 206559243Sobrien } 206659243Sobrien else 206759243Sobrien return -1; 206859243Sobrien 206959243Sobrien default: 207059243Sobrien if (!ws) /* Start a new word? */ 207159243Sobrien ws = p; 207259243Sobrien p++; 207359243Sobrien break; 207459243Sobrien } 207559243Sobrien return -1; 207659243Sobrien} 207759243Sobrien#endif /* HASHBANG */ 207859243Sobrien 207959243Sobrien#ifdef REMOTEHOST 208059243Sobrien 208159243Sobrienstatic sigret_t 208259243Sobrienpalarm(snum) 208359243Sobrien int snum; 208459243Sobrien{ 208559243Sobrien USE(snum); 208659243Sobrien#ifdef UNRELSIGS 208759243Sobrien if (snum) 208859243Sobrien (void) sigset(snum, SIG_IGN); 208959243Sobrien#endif /* UNRELSIGS */ 209059243Sobrien (void) alarm(0); 209159243Sobrien reset(); 209259243Sobrien 209359243Sobrien#ifndef SIGVOID 209459243Sobrien return (snum); 209559243Sobrien#endif 209659243Sobrien} 209759243Sobrien 209859243Sobrien 209959243Sobrienstatic void 210059243Sobriengetremotehost() 210159243Sobrien{ 210259243Sobrien const char *host = NULL; 210369408Sache#ifdef INET6 210469408Sache struct sockaddr_storage saddr; 210569408Sache int len = sizeof(struct sockaddr_storage); 210669408Sache static char hbuf[NI_MAXHOST]; 210769408Sache#else 210859243Sobrien struct hostent* hp; 210959243Sobrien struct sockaddr_in saddr; 211059243Sobrien int len = sizeof(struct sockaddr_in); 211169408Sache#endif 211259243Sobrien#if defined(UTHOST) && !defined(HAVENOUTMP) 211359243Sobrien char *sptr = NULL; 211459243Sobrien#endif 211559243Sobrien 211659243Sobrien if (getpeername(SHIN, (struct sockaddr *) &saddr, &len) != -1) { 211769408Sache#ifdef INET6 211859243Sobrien#if 0 211969408Sache int flag = 0; 212069408Sache#else 212169408Sache int flag = NI_NUMERICHOST; 212269408Sache#endif 212369408Sache 212469408Sache#ifdef NI_WITHSCOPEID 212569408Sache flag |= NI_WITHSCOPEID; 212669408Sache#endif 212769408Sache getnameinfo((struct sockaddr *)&saddr, len, hbuf, sizeof(hbuf), 212869408Sache NULL, 0, flag); 212969408Sache host = hbuf; 213069408Sache#else 213169408Sache#if 0 213259243Sobrien if ((hp = gethostbyaddr((char *)&saddr.sin_addr, sizeof(struct in_addr), 213359243Sobrien AF_INET)) != NULL) 213459243Sobrien host = hp->h_name; 213559243Sobrien else 213659243Sobrien#endif 213759243Sobrien host = inet_ntoa(saddr.sin_addr); 213869408Sache#endif 213959243Sobrien } 214059243Sobrien#if defined(UTHOST) && !defined(HAVENOUTMP) 214159243Sobrien else { 214259243Sobrien char *ptr; 214359243Sobrien char *name = utmphost(); 214459243Sobrien /* Avoid empty names and local X displays */ 214559243Sobrien if (name != NULL && *name != '\0' && *name != ':') { 214669408Sache struct in_addr addr; 214769408Sache 214859243Sobrien /* Look for host:display.screen */ 214969408Sache /* 215069408Sache * There is conflict with IPv6 address and X DISPLAY. So, 215169408Sache * we assume there is no IPv6 address in utmp and don't 215269408Sache * touch here. 215369408Sache */ 215459243Sobrien if ((sptr = strchr(name, ':')) != NULL) 215559243Sobrien *sptr = '\0'; 215669408Sache /* Leave IPv4 address as is */ 215769408Sache /* 215869408Sache * we use inet_addr here, not inet_aton because many systems 215969408Sache * have not caught up yet. 216069408Sache */ 216169408Sache addr.s_addr = inet_addr(name); 216269408Sache if (addr.s_addr != (unsigned long)~0) 216359243Sobrien host = name; 216459243Sobrien else { 216559243Sobrien if (sptr != name) { 216669408Sache#ifdef INET6 216769408Sache char *s, *domain; 216869408Sache char dbuf[MAXHOSTNAMELEN], cbuf[MAXHOSTNAMELEN]; 216969408Sache struct addrinfo hints, *res = NULL; 217069408Sache 217169408Sache memset(&hints, 0, sizeof(hints)); 217269408Sache hints.ai_family = PF_UNSPEC; 217369408Sache hints.ai_socktype = SOCK_STREAM; 217469408Sache hints.ai_flags = AI_PASSIVE | AI_CANONNAME; 217569408Sache#if defined(UTHOST) && !defined(HAVENOUTMP) 217669408Sache if (strlen(name) < utmphostsize()) 217769408Sache#else 217869408Sache if (name != NULL) 217969408Sache#endif 218069408Sache { 218169408Sache if (getaddrinfo(name, NULL, &hints, &res) != 0) 218269408Sache res = NULL; 218369408Sache } else if (gethostname(dbuf, sizeof(dbuf) - 1) == 0 && 218469408Sache (domain = strchr(dbuf, '.')) != NULL) { 218569408Sache for (s = strchr(name, '.'); 218669408Sache s != NULL; s = strchr(s + 1, '.')) { 218769408Sache if (*(s + 1) != '\0' && 218869408Sache (ptr = strstr(domain, s)) != NULL) { 218969408Sache len = s - name; 219069408Sache if (len + strlen(ptr) >= sizeof(cbuf)) 219169408Sache break; 219269408Sache strncpy(cbuf, name, len); 219369408Sache strcpy(cbuf + len, ptr); 219469408Sache if (getaddrinfo(cbuf, NULL, &hints, &res) != 0) 219569408Sache res = NULL; 219669408Sache break; 219769408Sache } 219869408Sache } 219969408Sache } 220069408Sache if (res != NULL) { 220169408Sache if (res->ai_canonname != NULL) { 220269408Sache strncpy(hbuf, res->ai_canonname, sizeof(hbuf)); 220369408Sache host = hbuf; 220469408Sache } 220569408Sache freeaddrinfo(res); 220669408Sache } 220769408Sache#else 220859243Sobrien if ((hp = gethostbyname(name)) == NULL) { 220959243Sobrien /* Try again eliminating the trailing domain */ 221059243Sobrien if ((ptr = strchr(name, '.')) != NULL) { 221159243Sobrien *ptr = '\0'; 221259243Sobrien if ((hp = gethostbyname(name)) != NULL) 221359243Sobrien host = hp->h_name; 221459243Sobrien *ptr = '.'; 221559243Sobrien } 221659243Sobrien } 221759243Sobrien else 221859243Sobrien host = hp->h_name; 221969408Sache#endif 222059243Sobrien } 222159243Sobrien } 222259243Sobrien } 222359243Sobrien } 222459243Sobrien#endif 222559243Sobrien 222659243Sobrien if (host) 222759243Sobrien tsetenv(STRREMOTEHOST, str2short(host)); 222859243Sobrien 222959243Sobrien#if defined(UTHOST) && !defined(HAVENOUTMP) 223059243Sobrien if (sptr) 223159243Sobrien *sptr = ':'; 223259243Sobrien#endif 223359243Sobrien} 223459243Sobrien 223559243Sobrien 223659243Sobrien/* 223759243Sobrien * From: <lesv@ppvku.ericsson.se> (Lennart Svensson) 223859243Sobrien */ 223959243Sobrienvoid 224059243Sobrienremotehost() 224159243Sobrien{ 224259243Sobrien /* Don't get stuck if the resolver does not work! */ 224359243Sobrien signalfun_t osig = sigset(SIGALRM, palarm); 224459243Sobrien 224559243Sobrien jmp_buf_t osetexit; 224659243Sobrien getexit(osetexit); 224759243Sobrien 224859243Sobrien (void) alarm(2); 224959243Sobrien 225059243Sobrien if (setexit() == 0) 225159243Sobrien getremotehost(); 225259243Sobrien 225359243Sobrien resexit(osetexit); 225459243Sobrien 225559243Sobrien (void) alarm(0); 225659243Sobrien (void) sigset(SIGALRM, osig); 225759243Sobrien 225859243Sobrien#ifdef YPBUGS 225959243Sobrien /* From: casper@fwi.uva.nl (Casper H.S. Dik), for Solaris 2.3 */ 226059243Sobrien fix_yp_bugs(); 226159243Sobrien#endif /* YPBUGS */ 226259243Sobrien 226359243Sobrien} 226459243Sobrien#endif /* REMOTEHOST */ 2265