Index: head/usr.bin/gprof/gprof.c =================================================================== --- head/usr.bin/gprof/gprof.c (revision 359679) +++ head/usr.bin/gprof/gprof.c (revision 359680) @@ -1,598 +1,599 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #if 0 #ifndef lint static char sccsid[] = "@(#)gprof.c 8.1 (Berkeley) 6/6/93"; #endif /* not lint */ #endif #include __FBSDID("$FreeBSD$"); #include #include #include #include +#define EXTERN #include "gprof.h" static int valcmp(const void *, const void *); static struct gmonhdr gmonhdr; static int lflag; static int Lflag; int main(int argc, char **argv) { char **sp; nltype **timesortnlp; char **defaultEs; --argc; argv++; debug = 0; bflag = TRUE; while ( *argv != 0 && **argv == '-' ) { (*argv)++; switch ( **argv ) { case 'a': aflag = TRUE; break; case 'b': bflag = FALSE; break; case 'C': Cflag = TRUE; cyclethreshold = atoi( *++argv ); break; case 'd': dflag = TRUE; setlinebuf(stdout); debug |= atoi( *++argv ); debug |= ANYDEBUG; # ifdef DEBUG printf("[main] debug = %d\n", debug); # else /* not DEBUG */ printf("gprof: -d ignored\n"); # endif /* DEBUG */ break; case 'E': ++argv; addlist( Elist , *argv ); Eflag = TRUE; addlist( elist , *argv ); eflag = TRUE; break; case 'e': addlist( elist , *++argv ); eflag = TRUE; break; case 'F': ++argv; addlist( Flist , *argv ); Fflag = TRUE; addlist( flist , *argv ); fflag = TRUE; break; case 'f': addlist( flist , *++argv ); fflag = TRUE; break; case 'k': addlist( kfromlist , *++argv ); addlist( ktolist , *++argv ); kflag = TRUE; break; case 'K': Kflag = TRUE; break; case 'l': lflag = 1; Lflag = 0; break; case 'L': Lflag = 1; lflag = 0; break; case 's': sflag = TRUE; break; case 'u': uflag = TRUE; break; case 'z': zflag = TRUE; break; } argv++; } if ( *argv != 0 ) { a_outname = *argv; argv++; } else { a_outname = A_OUTNAME; } if ( *argv != 0 ) { gmonname = *argv; argv++; } else { gmonname = (char *) malloc(strlen(a_outname)+6); strcpy(gmonname, a_outname); strcat(gmonname, ".gmon"); } /* * get information from the executable file. */ if ((Kflag && kernel_getnfile(a_outname, &defaultEs) == -1) || (!Kflag && elf_getnfile(a_outname, &defaultEs) == -1 #ifdef WITH_AOUT && aout_getnfile(a_outname, &defaultEs) == -1 #endif )) errx(1, "%s: bad format", a_outname); /* * sort symbol table. */ qsort(nl, nname, sizeof(nltype), valcmp); /* * turn off default functions */ for ( sp = defaultEs ; *sp ; sp++ ) { Eflag = TRUE; addlist( Elist , *sp ); eflag = TRUE; addlist( elist , *sp ); } /* * get information about mon.out file(s). */ do { getpfile( gmonname ); if ( *argv != 0 ) { gmonname = *argv; } } while ( *argv++ != 0 ); /* * how many ticks per second? * if we can't tell, report time in ticks. */ if (hz == 0) { hz = 1; fprintf(stderr, "time is in ticks, not seconds\n"); } /* * dump out a gmon.sum file if requested */ if ( sflag ) { dumpsum( GMONSUM ); } /* * assign samples to procedures */ asgnsamples(); /* * assemble the dynamic profile */ timesortnlp = doarcs(); /* * print the dynamic profile */ if(!lflag) { printgprof( timesortnlp ); } /* * print the flat profile */ if(!Lflag) { printprof(); } /* * print the index */ printindex(); exit(0); } /* * information from a gmon.out file is in two parts: * an array of sampling hits within pc ranges, * and the arcs. */ void getpfile(char *filename) { FILE *pfile; struct rawarc arc; pfile = openpfile(filename); readsamples(pfile); /* * the rest of the file consists of * a bunch of tuples. */ while ( fread( &arc , sizeof arc , 1 , pfile ) == 1 ) { # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[getpfile] frompc 0x%lx selfpc 0x%lx count %ld\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif /* DEBUG */ /* * add this arc */ tally( &arc ); } fclose(pfile); } FILE * openpfile(char *filename) { struct gmonhdr tmp; FILE *pfile; int size; int rate; if((pfile = fopen(filename, "r")) == NULL) err(1, "%s", filename); fread(&tmp, sizeof(struct gmonhdr), 1, pfile); if ( s_highpc != 0 && ( tmp.lpc != gmonhdr.lpc || tmp.hpc != gmonhdr.hpc || tmp.ncnt != gmonhdr.ncnt ) ) errx(1, "%s: incompatible with first gmon file", filename); gmonhdr = tmp; if ( gmonhdr.version == GMONVERSION ) { rate = gmonhdr.profrate; size = sizeof(struct gmonhdr); } else { fseek(pfile, sizeof(struct ophdr), SEEK_SET); size = sizeof(struct ophdr); gmonhdr.profrate = rate = hertz(); gmonhdr.version = GMONVERSION; } if (hz == 0) { hz = rate; } else if (hz != rate) errx(0, "%s: profile clock rate (%d) %s (%ld) in first gmon file", filename, rate, "incompatible with clock rate", hz); if ( gmonhdr.histcounter_type == 0 ) { /* Historical case. The type was u_short (2 bytes in practice). */ histcounter_type = 16; histcounter_size = 2; } else { histcounter_type = gmonhdr.histcounter_type; histcounter_size = abs(histcounter_type) / CHAR_BIT; } s_lowpc = (unsigned long) gmonhdr.lpc; s_highpc = (unsigned long) gmonhdr.hpc; lowpc = (unsigned long)gmonhdr.lpc / HISTORICAL_SCALE_2; highpc = (unsigned long)gmonhdr.hpc / HISTORICAL_SCALE_2; sampbytes = gmonhdr.ncnt - size; nsamples = sampbytes / histcounter_size; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[openpfile] hdr.lpc 0x%lx hdr.hpc 0x%lx hdr.ncnt %d\n", gmonhdr.lpc , gmonhdr.hpc , gmonhdr.ncnt ); printf( "[openpfile] s_lowpc 0x%lx s_highpc 0x%lx\n" , s_lowpc , s_highpc ); printf( "[openpfile] lowpc 0x%lx highpc 0x%lx\n" , lowpc , highpc ); printf( "[openpfile] sampbytes %d nsamples %d\n" , sampbytes , nsamples ); printf( "[openpfile] sample rate %ld\n" , hz ); } # endif /* DEBUG */ return(pfile); } void tally(struct rawarc *rawp) { nltype *parentp; nltype *childp; parentp = nllookup( rawp -> raw_frompc ); childp = nllookup( rawp -> raw_selfpc ); if ( parentp == 0 || childp == 0 ) return; if ( kflag && onlist( kfromlist , parentp -> name ) && onlist( ktolist , childp -> name ) ) { return; } childp -> ncall += rawp -> raw_count; # ifdef DEBUG if ( debug & TALLYDEBUG ) { printf( "[tally] arc from %s to %s traversed %ld times\n" , parentp -> name , childp -> name , rawp -> raw_count ); } # endif /* DEBUG */ addarc( parentp , childp , rawp -> raw_count ); } /* * dump out the gmon.sum file */ void dumpsum(const char *sumfile) { register nltype *nlp; register arctype *arcp; struct rawarc arc; FILE *sfile; if ( ( sfile = fopen ( sumfile , "w" ) ) == NULL ) err( 1 , "%s" , sumfile ); /* * dump the header; use the last header read in */ if ( fwrite( &gmonhdr , sizeof gmonhdr , 1 , sfile ) != 1 ) err( 1 , "%s" , sumfile ); /* * dump the samples */ if (fwrite(samples, histcounter_size, nsamples, sfile) != nsamples) err( 1 , "%s" , sumfile ); /* * dump the normalized raw arc information */ for ( nlp = nl ; nlp < npe ; nlp++ ) { for ( arcp = nlp -> children ; arcp ; arcp = arcp -> arc_childlist ) { arc.raw_frompc = arcp -> arc_parentp -> value; arc.raw_selfpc = arcp -> arc_childp -> value; arc.raw_count = arcp -> arc_count; if ( fwrite ( &arc , sizeof arc , 1 , sfile ) != 1 ) err( 1 , "%s" , sumfile ); # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[dumpsum] frompc 0x%lx selfpc 0x%lx count %ld\n" , arc.raw_frompc , arc.raw_selfpc , arc.raw_count ); } # endif /* DEBUG */ } } fclose( sfile ); } static int valcmp(const void *v1, const void *v2) { const nltype *p1 = (const nltype *)v1; const nltype *p2 = (const nltype *)v2; if ( p1 -> value < p2 -> value ) { return LESSTHAN; } if ( p1 -> value > p2 -> value ) { return GREATERTHAN; } return EQUALTO; } void readsamples(FILE *pfile) { int i; intmax_t sample; if (samples == 0) { samples = (double *) calloc(nsamples, sizeof(double)); if (samples == NULL) errx(0, "no room for %d sample pc's", nsamples); } for (i = 0; i < nsamples; i++) { fread(&sample, histcounter_size, 1, pfile); if (feof(pfile)) break; switch ( histcounter_type ) { case -8: samples[i] += *(int8_t *)&sample; break; case 8: samples[i] += *(u_int8_t *)&sample; break; case -16: samples[i] += *(int16_t *)&sample; break; case 16: samples[i] += *(u_int16_t *)&sample; break; case -32: samples[i] += *(int32_t *)&sample; break; case 32: samples[i] += *(u_int32_t *)&sample; break; case -64: samples[i] += *(int64_t *)&sample; break; case 64: samples[i] += *(u_int64_t *)&sample; break; default: err(1, "unsupported histogram counter type %d", histcounter_type); } } if (i != nsamples) errx(1, "unexpected EOF after reading %d/%d samples", --i , nsamples ); } /* * Assign samples to the procedures to which they belong. * * There are three cases as to where pcl and pch can be * with respect to the routine entry addresses svalue0 and svalue1 * as shown in the following diagram. overlap computes the * distance between the arrows, the fraction of the sample * that is to be credited to the routine which starts at svalue0. * * svalue0 svalue1 * | | * v v * * +-----------------------------------------------+ * | | * | ->| |<- ->| |<- ->| |<- | * | | | | | | * +---------+ +---------+ +---------+ * * ^ ^ ^ ^ ^ ^ * | | | | | | * pcl pch pcl pch pcl pch * * For the vax we assert that samples will never fall in the first * two bytes of any routine, since that is the entry mask, * thus we give call alignentries() to adjust the entry points if * the entry mask falls in one bucket but the code for the routine * doesn't start until the next bucket. In conjunction with the * alignment of routine addresses, this should allow us to have * only one sample for every four bytes of text space and never * have any overlap (the two end cases, above). */ void asgnsamples(void) { register int j; double ccnt; double thetime; unsigned long pcl, pch; register int i; unsigned long overlap; unsigned long svalue0, svalue1; /* read samples and assign to namelist symbols */ scale = highpc - lowpc; scale /= nsamples; alignentries(); for (i = 0, j = 1; i < nsamples; i++) { ccnt = samples[i]; if (ccnt == 0) continue; pcl = lowpc + (unsigned long)(scale * i); pch = lowpc + (unsigned long)(scale * (i + 1)); thetime = ccnt; # ifdef DEBUG if ( debug & SAMPLEDEBUG ) { printf( "[asgnsamples] pcl 0x%lx pch 0x%lx ccnt %.0f\n" , pcl , pch , ccnt ); } # endif /* DEBUG */ totime += thetime; for (j = j - 1; j < nname; j++) { svalue0 = nl[j].svalue; svalue1 = nl[j+1].svalue; /* * if high end of tick is below entry address, * go for next tick. */ if (pch < svalue0) break; /* * if low end of tick into next routine, * go for next routine. */ if (pcl >= svalue1) continue; overlap = min(pch, svalue1) - max(pcl, svalue0); if (overlap > 0) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] (0x%lx->0x%lx-0x%lx) %s gets %f ticks %lu overlap\n", nl[j].value / HISTORICAL_SCALE_2, svalue0, svalue1, nl[j].name, overlap * thetime / scale, overlap); } # endif /* DEBUG */ nl[j].time += overlap * thetime / scale; } } } # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[asgnsamples] totime %f\n", totime); } # endif /* DEBUG */ } unsigned long min(unsigned long a, unsigned long b) { if (ab) return(a); return(b); } /* * calculate scaled entry point addresses (to save time in asgnsamples), * and possibly push the scaled entry points over the entry mask, * if it turns out that the entry point is in one bucket and the code * for a routine is in the next bucket. */ void alignentries(void) { register struct nl *nlp; unsigned long bucket_of_entry; unsigned long bucket_of_code; for (nlp = nl; nlp < npe; nlp++) { nlp -> svalue = nlp -> value / HISTORICAL_SCALE_2; bucket_of_entry = (nlp->svalue - lowpc) / scale; bucket_of_code = (nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2 - lowpc) / scale; if (bucket_of_entry < bucket_of_code) { # ifdef DEBUG if (debug & SAMPLEDEBUG) { printf("[alignentries] pushing svalue 0x%lx to 0x%lx\n", nlp->svalue, nlp->svalue + OFFSET_OF_CODE / HISTORICAL_SCALE_2); } # endif /* DEBUG */ nlp->svalue += OFFSET_OF_CODE / HISTORICAL_SCALE_2; } } } Index: head/usr.bin/gprof/gprof.h =================================================================== --- head/usr.bin/gprof/gprof.h (revision 359679) +++ head/usr.bin/gprof/gprof.h (revision 359680) @@ -1,337 +1,344 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)gprof.h 8.1 (Berkeley) 6/6/93 * $FreeBSD$ */ #include #include #include #include #include #if __amd64__ # include "amd64.h" #endif #if __arm__ # include "arm.h" #endif #if __i386__ # include "i386.h" #endif #if __mips__ # include "mips.h" #endif #if __powerpc__ # include "powerpc.h" #endif #if __sparc64__ # include "sparc64.h" #endif #if __riscv # include "riscv.h" #endif /* * booleans */ typedef int bool; #define FALSE 0 #define TRUE 1 /* * Historical scale factor in profil(2)'s algorithm for converting * pc addresses to bucket numbers. This now just complicates the * scaling and makes bucket:pc densities of more than 1/2 useless. */ #define HISTORICAL_SCALE_2 2 +#ifndef EXTERN +#define EXTERN extern +#endif + /* * ticks per second */ -long hz; +EXTERN long hz; -size_t histcounter_size; -int histcounter_type; +EXTERN size_t histcounter_size; +EXTERN int histcounter_type; -char *a_outname; +EXTERN char *a_outname; #define A_OUTNAME "a.out" -char *gmonname; +EXTERN char *gmonname; #define GMONSUM "gmon.sum" /* * a constructed arc, * with pointers to the namelist entry of the parent and the child, * a count of how many times this arc was traversed, * and pointers to the next parent of this child and * the next child of this parent. */ struct arcstruct { struct nl *arc_parentp; /* pointer to parent's nl entry */ struct nl *arc_childp; /* pointer to child's nl entry */ long arc_count; /* num calls from parent to child */ double arc_time; /* time inherited along arc */ double arc_childtime; /* childtime inherited along arc */ struct arcstruct *arc_parentlist; /* parents-of-this-child list */ struct arcstruct *arc_childlist; /* children-of-this-parent list */ struct arcstruct *arc_next; /* list of arcs on cycle */ unsigned short arc_cyclecnt; /* num cycles involved in */ unsigned short arc_flags; /* see below */ }; typedef struct arcstruct arctype; /* * arc flags */ #define DEADARC 0x01 /* time should not propagate across the arc */ #define ONLIST 0x02 /* arc is on list of arcs in cycles */ /* * The symbol table; * for each external in the specified file we gather * its address, the number of calls and compute its share of CPU time. */ struct nl { const char *name; /* the name */ unsigned long value; /* the pc entry point */ unsigned long svalue; /* entry point aligned to histograms */ double time; /* ticks in this routine */ double childtime; /* cumulative ticks in children */ long ncall; /* how many times called */ long npropcall; /* times called by live arcs */ long selfcalls; /* how many calls to self */ double propfraction; /* what % of time propagates */ double propself; /* how much self time propagates */ double propchild; /* how much child time propagates */ short printflag; /* should this be printed? */ short flags; /* see below */ int index; /* index in the graph list */ int toporder; /* graph call chain top-sort order */ int cycleno; /* internal number of cycle on */ int parentcnt; /* number of live parent arcs */ struct nl *cyclehead; /* pointer to head of cycle */ struct nl *cnext; /* pointer to next member of cycle */ arctype *parents; /* list of caller arcs */ arctype *children; /* list of callee arcs */ }; typedef struct nl nltype; -nltype *nl; /* the whole namelist */ -nltype *npe; /* the virtual end of the namelist */ -int nname; /* the number of function names */ +EXTERN nltype *nl; /* the whole namelist */ +EXTERN nltype *npe; /* the virtual end of the namelist */ +EXTERN int nname; /* the number of function names */ #define HASCYCLEXIT 0x08 /* node has arc exiting from cycle */ #define CYCLEHEAD 0x10 /* node marked as head of a cycle */ #define VISITED 0x20 /* node visited during a cycle */ /* * The cycle list. * for each subcycle within an identified cycle, we gather * its size and the list of included arcs. */ struct cl { int size; /* length of cycle */ struct cl *next; /* next member of list */ arctype *list[1]; /* list of arcs in cycle */ /* actually longer */ }; typedef struct cl cltype; -arctype *archead; /* the head of arcs in current cycle list */ -cltype *cyclehead; /* the head of the list */ -int cyclecnt; /* the number of cycles found */ +EXTERN arctype *archead; /* the head of arcs in current cycle list */ +EXTERN cltype *cyclehead; /* the head of the list */ +EXTERN int cyclecnt; /* the number of cycles found */ #define CYCLEMAX 100 /* maximum cycles before cutting one of them */ /* * flag which marks a nl entry as topologically ``busy'' * flag which marks a nl entry as topologically ``not_numbered'' */ #define DFN_BUSY -1 #define DFN_NAN 0 /* * namelist entries for cycle headers. * the number of discovered cycles. */ -nltype *cyclenl; /* cycle header namelist */ -int ncycle; /* number of cycles discovered */ +EXTERN nltype *cyclenl; /* cycle header namelist */ +EXTERN int ncycle; /* number of cycles discovered */ /* * The header on the gmon.out file. * gmon.out consists of a struct phdr (defined in gmon.h) * and then an array of ncnt samples representing the * discretized program counter values. * * Backward compatible old style header */ struct ophdr { u_short *lpc; u_short *hpc; int ncnt; }; -int debug; +EXTERN int debug; /* * Each discretized pc sample has * a count of the number of samples in its range */ -double *samples; +EXTERN double *samples; -unsigned long s_lowpc; /* lowpc from the profile file */ -unsigned long s_highpc; /* highpc from the profile file */ -unsigned long lowpc, highpc; /* range profiled, in historical units */ -unsigned sampbytes; /* number of bytes of samples */ -int nsamples; /* number of samples */ -double actime; /* accumulated time thus far for putprofline */ -double totime; /* total time for all routines */ -double printtime; /* total of time being printed */ -double scale; /* scale factor converting samples to pc +EXTERN unsigned long s_lowpc; /* lowpc from the profile file */ +EXTERN unsigned long s_highpc; /* highpc from the profile file */ +/* range profiled, in historical units */ +EXTERN unsigned long lowpc, highpc; +EXTERN unsigned sampbytes; /* number of bytes of samples */ +EXTERN int nsamples; /* number of samples */ +/* accumulated time thus far for putprofline */ +EXTERN double actime; +EXTERN double totime; /* total time for all routines */ +EXTERN double printtime; /* total of time being printed */ +EXTERN double scale; /* scale factor converting samples to pc values: each sample covers scale bytes */ -unsigned char *textspace; /* text space of a.out in core */ -int cyclethreshold; /* with -C, minimum cycle size to ignore */ +EXTERN unsigned char *textspace; /* text space of a.out in core */ +/* with -C, minimum cycle size to ignore */ +EXTERN int cyclethreshold; /* * option flags, from a to z. */ -bool aflag; /* suppress static functions */ -bool bflag; /* blurbs, too */ -bool Cflag; /* find cut-set to eliminate cycles */ -bool dflag; /* debugging options */ -bool eflag; /* specific functions excluded */ -bool Eflag; /* functions excluded with time */ -bool fflag; /* specific functions requested */ -bool Fflag; /* functions requested with time */ -bool kflag; /* arcs to be deleted */ -bool Kflag; /* use the running kernel for symbols */ -bool sflag; /* sum multiple gmon.out files */ -bool uflag; /* suppress symbols hidden from C */ -bool zflag; /* zero time/called functions, too */ +EXTERN bool aflag; /* suppress static functions */ +EXTERN bool bflag; /* blurbs, too */ +EXTERN bool Cflag; /* find cut-set to eliminate cycles */ +EXTERN bool dflag; /* debugging options */ +EXTERN bool eflag; /* specific functions excluded */ +EXTERN bool Eflag; /* functions excluded with time */ +EXTERN bool fflag; /* specific functions requested */ +EXTERN bool Fflag; /* functions requested with time */ +EXTERN bool kflag; /* arcs to be deleted */ +EXTERN bool Kflag; /* use the running kernel for symbols */ +EXTERN bool sflag; /* sum multiple gmon.out files */ +EXTERN bool uflag; /* suppress symbols hidden from C */ +EXTERN bool zflag; /* zero time/called functions, too */ /* * structure for various string lists */ struct stringlist { struct stringlist *next; char *string; }; -struct stringlist *elist; -struct stringlist *Elist; -struct stringlist *flist; -struct stringlist *Flist; -struct stringlist *kfromlist; -struct stringlist *ktolist; +extern struct stringlist *elist; +extern struct stringlist *Elist; +extern struct stringlist *flist; +extern struct stringlist *Flist; +extern struct stringlist *kfromlist; +extern struct stringlist *ktolist; /* * function declarations */ void addarc(nltype *, nltype *, long); bool addcycle(arctype **, arctype **); void addlist(struct stringlist *, char *); void alignentries(void); #ifdef WITH_AOUT int aout_getnfile(const char *, char ***); #endif int arccmp(arctype *, arctype *); arctype *arclookup(nltype *, nltype *); void asgnsamples(void); void compresslist(void); bool cycleanalyze(void); void cyclelink(void); void cycletime(void); bool descend(nltype *, arctype **, arctype **); void dfn(nltype *); bool dfn_busy(nltype *); void dfn_findcycle(nltype *); void dfn_init(void); bool dfn_numbered(nltype *); void dfn_post_visit(nltype *); void dfn_pre_visit(nltype *); void dfn_self_cycle(nltype *); nltype **doarcs(void); void doflags(void); void dotime(void); void dumpsum(const char *); int elf_getnfile(const char *, char ***); void flatprofheader(void); void flatprofline(nltype *); void getpfile(char *); void gprofheader(void); void gprofline(register nltype *); int hertz(void); void inheritflags(nltype *); int kernel_getnfile(const char *, char ***); /* main(); */ unsigned long max(unsigned long, unsigned long); int membercmp(nltype *, nltype *); unsigned long min(unsigned long, unsigned long); nltype *nllookup(unsigned long); bool onlist(struct stringlist *, const char *); FILE *openpfile(char *); void printblurb(const char *); void printchildren(nltype *); void printcycle(nltype *); void printgprof(nltype **); void printindex(void); void printmembers(nltype *); void printname(nltype *); void printparents(nltype *); void printprof(void); void printsubcycle(cltype *); void readsamples(FILE *); void sortchildren(nltype *); void sortmembers(nltype *); void sortparents(nltype *); void tally(struct rawarc *); void timepropagate(nltype *); int totalcmp(const void *, const void *); #define LESSTHAN -1 #define EQUALTO 0 #define GREATERTHAN 1 #define DFNDEBUG 1 #define CYCLEDEBUG 2 #define ARCDEBUG 4 #define TALLYDEBUG 8 #define TIMEDEBUG 16 #define SAMPLEDEBUG 32 #define AOUTDEBUG 64 #define CALLDEBUG 128 #define LOOKUPDEBUG 256 #define PROPDEBUG 512 #define BREAKCYCLE 1024 #define SUBCYCLELIST 2048 #define ANYDEBUG 4096 Index: head/usr.bin/mail/glob.h =================================================================== --- head/usr.bin/mail/glob.h (revision 359679) +++ head/usr.bin/mail/glob.h (revision 359680) @@ -1,100 +1,100 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)glob.h 8.1 (Berkeley) 6/6/93 * * $FreeBSD$ */ /* * A bunch of global variable declarations lie herein. * def.h must be included first. */ -int msgCount; /* Count of messages read in */ -int rcvmode; /* True if receiving mail */ -int sawcom; /* Set after first command */ -char *Tflag; /* -T temp file for netnews */ -int senderr; /* An error while checking */ -int edit; /* Indicates editing a file */ -int readonly; /* Will be unable to rewrite file */ -int noreset; /* String resets suspended */ -int sourcing; /* Currently reading variant file */ -int loading; /* Loading user definitions */ -int cond; /* Current state of conditional exc. */ -FILE *itf; /* Input temp file buffer */ -FILE *otf; /* Output temp file buffer */ -int image; /* File descriptor for image of msg */ -FILE *input; /* Current command input file */ -char mailname[PATHSIZE]; /* Name of current file */ -char prevfile[PATHSIZE]; /* Name of previous file */ -char *homedir; /* Path name of home directory */ -char *myname; /* My login name */ -off_t mailsize; /* Size of system mailbox */ -int lexnumber; /* Number of TNUMBER from scan() */ -char lexstring[STRINGLEN]; /* String from TSTRING, scan() */ -int regretp; /* Pointer to TOS of regret tokens */ -int regretstack[REGDEP]; /* Stack of regretted tokens */ -char *string_stack[REGDEP]; /* Stack of regretted strings */ -int numberstack[REGDEP]; /* Stack of regretted numbers */ -struct message *dot; /* Pointer to current message */ -struct message *message; /* The actual message structure */ -struct var *variables[HSHSIZE]; /* Pointer to active var list */ -struct grouphead *groups[HSHSIZE];/* Pointer to active groups */ -struct ignoretab ignore[2]; /* ignored and retained fields +extern int msgCount; /* Count of messages read in */ +extern int rcvmode; /* True if receiving mail */ +extern int sawcom; /* Set after first command */ +extern char *Tflag; /* -T temp file for netnews */ +extern int senderr; /* An error while checking */ +extern int edit; /* Indicates editing a file */ +extern int readonly; /* Will be unable to rewrite file */ +extern int noreset; /* String resets suspended */ +extern int sourcing; /* Currently reading variant file */ +extern int loading; /* Loading user definitions */ +extern int cond; /* Current state of conditional exc. */ +extern FILE *itf; /* Input temp file buffer */ +extern FILE *otf; /* Output temp file buffer */ +extern int image; /* File descriptor for image of msg */ +extern FILE *input; /* Current command input file */ +extern char mailname[PATHSIZE]; /* Name of current file */ +extern char prevfile[PATHSIZE]; /* Name of previous file */ +extern char *homedir; /* Path name of home directory */ +extern char *myname; /* My login name */ +extern off_t mailsize; /* Size of system mailbox */ +extern int lexnumber; /* Number of TNUMBER from scan() */ +extern char lexstring[STRINGLEN]; /* String from TSTRING, scan() */ +extern int regretp; /* Pointer to TOS of regret tokens */ +extern int regretstack[REGDEP]; /* Stack of regretted tokens */ +extern char *string_stack[REGDEP]; /* Stack of regretted strings */ +extern int numberstack[REGDEP]; /* Stack of regretted numbers */ +extern struct message *dot; /* Pointer to current message */ +extern struct message *message; /* The actual message structure */ +extern struct var *variables[HSHSIZE]; /* Pointer to active var list */ +extern struct grouphead *groups[HSHSIZE];/* Pointer to active groups */ +extern struct ignoretab ignore[2]; /* ignored and retained fields 0 is ignore, 1 is retain */ -struct ignoretab saveignore[2]; /* ignored and retained fields +extern struct ignoretab saveignore[2]; /* ignored and retained fields on save to folder */ -struct ignoretab ignoreall[2]; /* special, ignore all headers */ -char **altnames; /* List of alternate names for user */ -int debug; /* Debug flag set */ -int screenwidth; /* Screen width, or best guess */ -int screenheight; /* Screen height, or best guess, +extern struct ignoretab ignoreall[2]; /* special, ignore all headers */ +extern char **altnames; /* List of alternate names for user */ +extern int debug; /* Debug flag set */ +extern int screenwidth; /* Screen width, or best guess */ +extern int screenheight; /* Screen height, or best guess, for "header" command */ -int realscreenheight; /* the real screen height */ +extern int realscreenheight; /* the real screen height */ #include -jmp_buf srbuf; +extern jmp_buf srbuf; /* * The pointers for the string allocation routines, * there are NSPACE independent areas. * The first holds STRINGSIZE bytes, the next * twice as much, and so on. */ #define NSPACE 25 /* Total number of string spaces */ -struct strings { +extern struct strings { char *s_topFree; /* Beginning of this area */ char *s_nextFree; /* Next alloctable place here */ unsigned s_nleft; /* Number of bytes left here */ } stringdope[NSPACE]; Index: head/usr.bin/mail/main.c =================================================================== --- head/usr.bin/mail/main.c (revision 359679) +++ head/usr.bin/mail/main.c (revision 359680) @@ -1,349 +1,392 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1980, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)main.c 8.2 (Berkeley) 4/20/95"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); #include "rcv.h" #include #include "extern.h" /* * Mail -- a mail program * * Startup -- interface with user. */ +int msgCount; +int rcvmode; +int sawcom; +char *Tflag; +int senderr; +int edit; +int readonly; +int noreset; +int sourcing; +int loading; +int cond; +FILE *itf; +FILE *otf; +int image; +FILE *input; +char mailname[PATHSIZE]; +char prevfile[PATHSIZE]; +char *homedir; +char *myname; +off_t mailsize; +int lexnumber; +char lexstring[STRINGLEN]; +int regretp; +int regretstack[REGDEP]; +char *string_stack[REGDEP]; +int numberstack[REGDEP]; +struct message *dot; +struct message *message; +struct var *variables[HSHSIZE]; +struct grouphead *groups[HSHSIZE]; +struct ignoretab ignore[2]; + +struct ignoretab saveignore[2]; + +struct ignoretab ignoreall[2]; +char **altnames; +int debug; +int screenwidth; +int screenheight; + +int realscreenheight; + +jmp_buf srbuf; static jmp_buf hdrjmp; extern const char *version; int main(int argc, char *argv[]) { int i; struct name *to, *cc, *bcc, *smopts; char *subject, *replyto; char *ef, *rc; char nosrc = 0; sig_t prevint; /* * Set up a reasonable environment. * Figure out whether we are being run interactively, * start the SIGCHLD catcher, and so forth. */ (void)signal(SIGCHLD, sigchild); if (isatty(0)) assign("interactive", ""); image = -1; /* * Now, determine how we are being used. * We successively pick off - flags. * If there is anything left, it is the base of the list * of users to mail to. Argp will be set to point to the * first of these users. */ ef = NULL; to = NULL; cc = NULL; bcc = NULL; smopts = NULL; subject = NULL; while ((i = getopt(argc, argv, "FEHINT:b:c:edfins:u:v")) != -1) { switch (i) { case 'T': /* * Next argument is temp file to write which * articles have been read/deleted for netnews. */ Tflag = optarg; if ((i = open(Tflag, O_CREAT | O_TRUNC | O_WRONLY, 0600)) < 0) err(1, "%s", Tflag); (void)close(i); break; case 'u': /* * Next argument is person to pretend to be. */ myname = optarg; unsetenv("MAIL"); break; case 'i': /* * User wants to ignore interrupts. * Set the variable "ignore" */ assign("ignore", ""); break; case 'd': debug++; break; case 'e': /* * User wants to check mail and exit. */ assign("checkmode", ""); break; case 'H': /* * User wants a header summary only. */ assign("headersummary", ""); break; case 'F': /* * User wants to record messages to files * named after first recipient username. */ assign("recordrecip", ""); break; case 's': /* * Give a subject field for sending from * non terminal */ subject = optarg; break; case 'f': /* * User is specifying file to "edit" with Mail, * as opposed to reading system mailbox. * If no argument is given after -f, we read his * mbox file. * * getopt() can't handle optional arguments, so here * is an ugly hack to get around it. */ if ((argv[optind] != NULL) && (argv[optind][0] != '-')) ef = argv[optind++]; else ef = "&"; break; case 'n': /* * User doesn't want to source /usr/lib/Mail.rc */ nosrc++; break; case 'N': /* * Avoid initial header printing. */ assign("noheader", ""); break; case 'v': /* * Send mailer verbose flag */ assign("verbose", ""); break; case 'I': /* * We're interactive */ assign("interactive", ""); break; case 'c': /* * Get Carbon Copy Recipient list */ cc = cat(cc, nalloc(optarg, GCC)); break; case 'b': /* * Get Blind Carbon Copy Recipient list */ bcc = cat(bcc, nalloc(optarg, GBCC)); break; case 'E': /* * Don't send empty files. */ assign("dontsendempty", ""); break; case '?': fprintf(stderr, "\ Usage: %s [-dEiInv] [-s subject] [-c cc-addr] [-b bcc-addr] [-F] to-addr ...\n\ %*s [-sendmail-option ...]\n\ %s [-dEHiInNv] [-F] -f [name]\n\ %s [-dEHiInNv] [-F] [-u user]\n\ %s [-d] -e [-f name]\n", __progname, (int)strlen(__progname), "", __progname, __progname, __progname); exit(1); } } for (i = optind; (argv[i] != NULL) && (*argv[i] != '-'); i++) to = cat(to, nalloc(argv[i], GTO)); for (; argv[i] != NULL; i++) smopts = cat(smopts, nalloc(argv[i], 0)); /* * Check for inconsistent arguments. */ if (to == NULL && (subject != NULL || cc != NULL || bcc != NULL)) errx(1, "You must specify direct recipients with -s, -c, or -b."); if (ef != NULL && to != NULL) errx(1, "Cannot give -f and people to send to."); tinit(); setscreensize(); input = stdin; rcvmode = !to; spreserve(); if (!nosrc) { char *s, *path_rc; if ((path_rc = malloc(sizeof(_PATH_MASTER_RC))) == NULL) err(1, "malloc(path_rc) failed"); strcpy(path_rc, _PATH_MASTER_RC); while ((s = strsep(&path_rc, ":")) != NULL) if (*s != '\0') load(s); } /* * Expand returns a savestr, but load only uses the file name * for fopen, so it's safe to do this. */ if ((rc = getenv("MAILRC")) == NULL) rc = "~/.mailrc"; load(expand(rc)); replyto = value("REPLYTO"); if (!rcvmode) { mail(to, cc, bcc, smopts, subject, replyto); /* * why wait? */ exit(senderr); } if(value("checkmode") != NULL) { if (ef == NULL) ef = "%"; if (setfile(ef) <= 0) /* Either an error has occurred, or no mail */ exit(1); else exit(0); /* NOTREACHED */ } /* * Ok, we are reading mail. * Decide whether we are editing a mailbox or reading * the system mailbox, and open up the right stuff. */ if (ef == NULL) ef = "%"; if (setfile(ef) < 0) exit(1); /* error already reported */ if (setjmp(hdrjmp) == 0) { if ((prevint = signal(SIGINT, SIG_IGN)) != SIG_IGN) (void)signal(SIGINT, hdrstop); if (value("quiet") == NULL) printf("Mail version %s. Type ? for help.\n", version); announce(); (void)fflush(stdout); (void)signal(SIGINT, prevint); } /* If we were in header summary mode, it's time to exit. */ if (value("headersummary") != NULL) exit(0); commands(); (void)signal(SIGHUP, SIG_IGN); (void)signal(SIGINT, SIG_IGN); (void)signal(SIGQUIT, SIG_IGN); quit(); exit(0); } /* * Interrupt printing of the headers. */ /*ARGSUSED*/ void hdrstop(int signo __unused) { (void)fflush(stdout); fprintf(stderr, "\nInterrupt\n"); longjmp(hdrjmp, 1); } /* * Compute what the screen size for printing headers should be. * We use the following algorithm for the height: * If baud rate < 1200, use 9 * If baud rate = 1200, use 14 * If baud rate > 1200, use 24 or ws_row * Width is either 80 or ws_col; */ void setscreensize(void) { struct termios tbuf; struct winsize ws; speed_t speed; if (ioctl(1, TIOCGWINSZ, (char *)&ws) < 0) ws.ws_col = ws.ws_row = 0; if (tcgetattr(1, &tbuf) < 0) speed = B9600; else speed = cfgetospeed(&tbuf); if (speed < B1200) screenheight = 9; else if (speed == B1200) screenheight = 14; else if (ws.ws_row != 0) screenheight = ws.ws_row; else screenheight = 24; if ((realscreenheight = ws.ws_row) == 0) realscreenheight = 24; if ((screenwidth = ws.ws_col) == 0) screenwidth = 80; } Index: head/usr.bin/mail/strings.c =================================================================== --- head/usr.bin/mail/strings.c (revision 359679) +++ head/usr.bin/mail/strings.c (revision 359680) @@ -1,126 +1,128 @@ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1980, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #ifndef lint #if 0 static char sccsid[] = "@(#)strings.c 8.1 (Berkeley) 6/6/93"; #endif #endif /* not lint */ #include __FBSDID("$FreeBSD$"); /* * Mail -- a mail program * * String allocation routines. * Strings handed out here are reclaimed at the top of the command * loop each time, so they need not be freed. */ #include "rcv.h" #include "extern.h" +struct strings stringdope[NSPACE]; + /* * Allocate size more bytes of space and return the address of the * first byte to the caller. An even number of bytes are always * allocated so that the space will always be on a word boundary. * The string spaces are of exponentially increasing size, to satisfy * the occasional user with enormous string size requests. */ char * salloc(int size) { char *t; int s, index; struct strings *sp; s = size; s += (sizeof(char *) - 1); s &= ~(sizeof(char *) - 1); index = 0; for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) { if (sp->s_topFree == NULL && (STRINGSIZE << index) >= s) break; if (sp->s_nleft >= s) break; index++; } if (sp >= &stringdope[NSPACE]) errx(1, "String too large"); if (sp->s_topFree == NULL) { index = sp - &stringdope[0]; if ((sp->s_topFree = malloc(STRINGSIZE << index)) == NULL) err(1, "No room for space %d", index); sp->s_nextFree = sp->s_topFree; sp->s_nleft = STRINGSIZE << index; } sp->s_nleft -= s; t = sp->s_nextFree; sp->s_nextFree += s; return (t); } /* * Reset the string area to be empty. * Called to free all strings allocated * since last reset. */ void sreset(void) { struct strings *sp; int index; if (noreset) return; index = 0; for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) { if (sp->s_topFree == NULL) continue; sp->s_nextFree = sp->s_topFree; sp->s_nleft = STRINGSIZE << index; index++; } } /* * Make the string area permanent. * Meant to be called in main, after initialization. */ void spreserve(void) { struct strings *sp; for (sp = &stringdope[0]; sp < &stringdope[NSPACE]; sp++) sp->s_topFree = NULL; } Index: head/usr.bin/tip/tip/tip.c =================================================================== --- head/usr.bin/tip/tip/tip.c (revision 359679) +++ head/usr.bin/tip/tip/tip.c (revision 359680) @@ -1,639 +1,640 @@ /* $OpenBSD: tip.c,v 1.30 2006/08/18 03:06:18 jason Exp $ */ /* $NetBSD: tip.c,v 1.13 1997/04/20 00:03:05 mellon Exp $ */ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1983, 1993 * The Regents of the University of California. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #ifndef lint static const char copyright[] = "@(#) Copyright (c) 1983, 1993\n\ The Regents of the University of California. All rights reserved.\n"; #endif /* not lint */ #ifndef lint #if 0 static char sccsid[] = "@(#)tip.c 8.1 (Berkeley) 6/6/93"; static const char rcsid[] = "$OpenBSD: tip.c,v 1.30 2006/08/18 03:06:18 jason Exp $"; #endif #endif /* not lint */ /* * tip - UNIX link to other systems * tip [-v] [-speed] system-name * or * cu phone-number [-s speed] [-l line] [-a acu] */ +#define EXTERN #include "tip.h" #include "pathnames.h" int disc = TTYDISC; /* tip normally runs this way */ char PNbuf[256]; /* This limits the size of a number */ static void intprompt(int); static void tipin(void); static int escape(void); int main(int argc, char *argv[]) { char *sys = NOSTR, sbuf[12], *p; int i; /* XXX preserve previous braindamaged behavior */ setboolean(value(DC), TRUE); gid = getgid(); egid = getegid(); uid = getuid(); euid = geteuid(); if (equal(__progname, "cu")) { cumode = 1; cumain(argc, argv); goto cucommon; } if (argc > 4) { fprintf(stderr, "usage: tip [-v] [-speed] [system-name]\n"); exit(1); } if (!isatty(0)) { fprintf(stderr, "%s: must be interactive\n", __progname); exit(1); } for (; argc > 1; argv++, argc--) { if (argv[1][0] != '-') sys = argv[1]; else switch (argv[1][1]) { case 'v': vflag++; break; case 'n': noesc++; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': BR = atoi(&argv[1][1]); break; default: fprintf(stderr, "%s: %s, unknown option\n", __progname, argv[1]); break; } } if (sys == NOSTR) goto notnumber; if (isalpha(*sys)) goto notnumber; /* * System name is really a phone number... * Copy the number then stomp on the original (in case the number * is private, we don't want 'ps' or 'w' to find it). */ if (strlen(sys) > sizeof PNbuf - 1) { fprintf(stderr, "%s: phone number too long (max = %d bytes)\n", __progname, (int)sizeof(PNbuf) - 1); exit(1); } strlcpy(PNbuf, sys, sizeof PNbuf - 1); for (p = sys; *p; p++) *p = '\0'; PN = PNbuf; (void)snprintf(sbuf, sizeof(sbuf), "tip%ld", BR); sys = sbuf; notnumber: (void)signal(SIGINT, cleanup); (void)signal(SIGQUIT, cleanup); (void)signal(SIGHUP, cleanup); (void)signal(SIGTERM, cleanup); (void)signal(SIGCHLD, SIG_DFL); if ((i = hunt(sys)) == 0) { printf("all ports busy\n"); exit(3); } if (i == -1) { printf("link down\n"); (void)uu_unlock(uucplock); exit(3); } setbuf(stdout, NULL); loginit(); /* * Now that we have the logfile and the ACU open * return to the real uid and gid. These things will * be closed on exit. Swap real and effective uid's * so we can get the original permissions back * for removing the uucp lock. */ user_uid(); /* * Kludge, their's no easy way to get the initialization * in the right order, so force it here */ if ((PH = getenv("PHONES")) == NOSTR) PH = _PATH_PHONES; vinit(); /* init variables */ setparity("none"); /* set the parity table */ /* * Hardwired connections require the * line speed set before they make any transmissions * (this is particularly true of things like a DF03-AC) */ if (HW && ttysetup(number(value(BAUDRATE)))) { fprintf(stderr, "%s: bad baud rate %ld\n", __progname, number(value(BAUDRATE))); daemon_uid(); (void)uu_unlock(uucplock); exit(3); } if ((p = con())) { printf("\07%s\n[EOT]\n", p); daemon_uid(); (void)uu_unlock(uucplock); exit(1); } if (!HW && ttysetup(number(value(BAUDRATE)))) { fprintf(stderr, "%s: bad baud rate %ld\n", __progname, number(value(BAUDRATE))); daemon_uid(); (void)uu_unlock(uucplock); exit(3); } cucommon: /* * From here down the code is shared with * the "cu" version of tip. */ i = fcntl(FD, F_GETFL); if (i == -1) { perror("fcntl"); cleanup(0); } i = fcntl(FD, F_SETFL, i & ~O_NONBLOCK); if (i == -1) { perror("fcntl"); cleanup(0); } tcgetattr(0, &defterm); gotdefterm = 1; term = defterm; term.c_lflag &= ~(ICANON|IEXTEN|ECHO); term.c_iflag &= ~(INPCK|ICRNL); term.c_oflag &= ~OPOST; term.c_cc[VMIN] = 1; term.c_cc[VTIME] = 0; defchars = term; term.c_cc[VINTR] = term.c_cc[VQUIT] = term.c_cc[VSUSP] = term.c_cc[VDSUSP] = term.c_cc[VDISCARD] = term.c_cc[VLNEXT] = _POSIX_VDISABLE; raw(); pipe(fildes); pipe(repdes); (void)signal(SIGALRM, timeout); if (value(LINEDISC) != TTYDISC) { int ld = (int)(intptr_t)value(LINEDISC); ioctl(FD, TIOCSETD, &ld); } /* * Everything's set up now: * connection established (hardwired or dialup) * line conditioned (baud rate, mode, etc.) * internal data structures (variables) * so, fork one process for local side and one for remote. */ printf(cumode ? "Connected\r\n" : "\07connected\r\n"); tipin_pid = getpid(); if ((tipout_pid = fork())) tipin(); else tipout(); exit(0); } void cleanup(int signo) { daemon_uid(); (void)uu_unlock(uucplock); if (odisc) ioctl(0, TIOCSETD, &odisc); unraw(); if (signo && tipout_pid) { kill(tipout_pid, signo); wait(NULL); } exit(0); } /* * Muck with user ID's. We are setuid to the owner of the lock * directory when we start. user_uid() reverses real and effective * ID's after startup, to run with the user's permissions. * daemon_uid() switches back to the privileged uid for unlocking. * Finally, to avoid running a shell with the wrong real uid, * shell_uid() sets real and effective uid's to the user's real ID. */ static int uidswapped; void user_uid(void) { if (uidswapped == 0) { seteuid(uid); uidswapped = 1; } } void daemon_uid(void) { if (uidswapped) { seteuid(euid); uidswapped = 0; } } void shell_uid(void) { setegid(gid); seteuid(uid); } /* * put the controlling keyboard into raw mode */ void raw(void) { tcsetattr(0, TCSADRAIN, &term); } /* * return keyboard to normal mode */ void unraw(void) { if (gotdefterm) tcsetattr(0, TCSADRAIN, &defterm); } /* * give up exclusive tty access */ void unexcl() { ioctl(FD, TIOCNXCL, 0); } static jmp_buf promptbuf; /* * Print string ``s'', then read a string * in from the terminal. Handles signals & allows use of * normal erase and kill characters. */ int prompt(char *s, char *p, size_t sz) { int c; char *b = p; sig_t oint, oquit; stoprompt = 0; oint = signal(SIGINT, intprompt); oquit = signal(SIGQUIT, SIG_IGN); unraw(); printf("%s", s); if (setjmp(promptbuf) == 0) while ((c = getchar()) != EOF && (*p = c) != '\n' && --sz > 0) p++; *p = '\0'; raw(); (void)signal(SIGINT, oint); (void)signal(SIGQUIT, oquit); return (stoprompt || p == b); } /* * Interrupt service routine during prompting */ /*ARGSUSED*/ static void intprompt(int signo) { (void)signal(SIGINT, SIG_IGN); stoprompt = 1; printf("\r\n"); longjmp(promptbuf, 1); } /* * ****TIPIN TIPIN**** */ static void tipin(void) { int bol = 1; int gch; char ch; /* * Kinda klugey here... * check for scripting being turned on from the .tiprc file, * but be careful about just using setscript(), as we may * send a SIGEMT before tipout has a chance to set up catching * it; so wait a second, then setscript() */ if (boolean(value(SCRIPT))) { sleep(1); setscript(); } while (1) { gch = getchar(); if (gch == EOF) return; gch = gch & STRIP_PAR; if ((gch == character(value(ESCAPE))) && bol) { if (!noesc) { gch = escape(); if (gch == EOF) return; if (gch == 0) continue; } } else if (!cumode && gch == character(value(RAISECHAR))) { setboolean(value(RAISE), !boolean(value(RAISE))); continue; } else if (gch == '\r') { bol = 1; ch = gch; parwrite(FD, &ch, 1); if (boolean(value(HALFDUPLEX))) printf("\r\n"); continue; } else if (!cumode && gch == character(value(FORCE))) { gch = getchar(); if (gch == EOF) return; gch = gch & STRIP_PAR; } bol = any(gch, value(EOL)); if (boolean(value(RAISE)) && islower(gch)) gch = toupper(gch); ch = gch; parwrite(FD, &ch, 1); if (boolean(value(HALFDUPLEX))) printf("%c", ch); } } extern esctable_t etable[]; /* * Escape handler -- * called on recognition of ``escapec'' at the beginning of a line */ static int escape(void) { int gch; esctable_t *p; char c = character(value(ESCAPE)); gch = getchar(); if (gch == EOF) return (EOF); gch = gch & STRIP_PAR; for (p = etable; p->e_char; p++) if (p->e_char == gch) { if ((p->e_flags&PRIV) && uid) continue; printf("%s", ctrl(c)); (*p->e_func)(gch); return (0); } /* ESCAPE ESCAPE forces ESCAPE */ if (c != gch) parwrite(FD, &c, 1); return (gch); } int any(int cc, char *p) { char c = cc; while (p && *p) if (*p++ == c) return (1); return (0); } size_t size(char *s) { size_t i = 0; while (s && *s++) i++; return (i); } char * interp(char *s) { static char buf[256]; char *p = buf, c, *q; while ((c = *s++)) { for (q = "\nn\rr\tt\ff\033E\bb"; *q; q++) if (*q++ == c) { *p++ = '\\'; *p++ = *q; goto next; } if (c < 040) { *p++ = '^'; *p++ = c + 'A'-1; } else if (c == 0177) { *p++ = '^'; *p++ = '?'; } else *p++ = c; next: ; } *p = '\0'; return (buf); } char * ctrl(char c) { static char s[3]; if (c < 040 || c == 0177) { s[0] = '^'; s[1] = c == 0177 ? '?' : c+'A'-1; s[2] = '\0'; } else { s[0] = c; s[1] = '\0'; } return (s); } /* * Help command */ void help(int c) { esctable_t *p; printf("%c\r\n", c); for (p = etable; p->e_char; p++) { if ((p->e_flags&PRIV) && uid) continue; printf("%2s", ctrl(character(value(ESCAPE)))); printf("%-2s %c %s\r\n", ctrl(p->e_char), p->e_flags&EXP ? '*': ' ', p->e_help); } } /* * Set up the "remote" tty's state */ int ttysetup(int speed) { struct termios cntrl; if (tcgetattr(FD, &cntrl)) return (-1); cfsetspeed(&cntrl, speed); cntrl.c_cflag &= ~(CSIZE|PARENB); cntrl.c_cflag |= CS8; if (boolean(value(DC))) cntrl.c_cflag |= CLOCAL; if (boolean(value(HARDWAREFLOW))) cntrl.c_cflag |= CRTSCTS; cntrl.c_iflag &= ~(ISTRIP|ICRNL); cntrl.c_oflag &= ~OPOST; cntrl.c_lflag &= ~(ICANON|ISIG|IEXTEN|ECHO); cntrl.c_cc[VMIN] = 1; cntrl.c_cc[VTIME] = 0; if (boolean(value(TAND))) cntrl.c_iflag |= IXOFF; return (tcsetattr(FD, TCSAFLUSH, &cntrl)); } static char partab[0200]; /* * Do a write to the remote machine with the correct parity. * We are doing 8 bit wide output, so we just generate a character * with the right parity and output it. */ void parwrite(int fd, char *buf, size_t n) { size_t i; char *bp; bp = buf; if (bits8 == 0) for (i = 0; i < n; i++) { *bp = partab[(*bp) & 0177]; bp++; } if (write(fd, buf, n) < 0) { if (errno == EIO || errno == ENXIO) tipabort("Lost carrier."); /* this is questionable */ perror("write"); } } /* * Build a parity table with appropriate high-order bit. */ void setparity(char *defparity) { int i, flip, clr, set; char *parity; extern const unsigned char evenpartab[]; if (value(PARITY) == NOSTR) value(PARITY) = defparity; parity = value(PARITY); if (equal(parity, "none")) { bits8 = 1; return; } bits8 = 0; flip = 0; clr = 0377; set = 0; if (equal(parity, "odd")) flip = 0200; /* reverse bit 7 */ else if (equal(parity, "zero")) clr = 0177; /* turn off bit 7 */ else if (equal(parity, "one")) set = 0200; /* turn on bit 7 */ else if (!equal(parity, "even")) { (void) fprintf(stderr, "%s: unknown parity value\r\n", parity); (void) fflush(stderr); } for (i = 0; i < 0200; i++) partab[i] = ((evenpartab[i] ^ flip) | set) & clr; } Index: head/usr.bin/tip/tip/tip.h =================================================================== --- head/usr.bin/tip/tip/tip.h (revision 359679) +++ head/usr.bin/tip/tip/tip.h (revision 359680) @@ -1,356 +1,360 @@ /* $OpenBSD: tip.h,v 1.27 2006/08/18 03:06:18 jason Exp $ */ /* $NetBSD: tip.h,v 1.7 1997/04/20 00:02:46 mellon Exp $ */ /* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-3-Clause * * Copyright (c) 1989, 1993 * The Regents of the University of California. All rights reserved. * * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the University nor the names of its contributors * may be used to endorse or promote products derived from this software * without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * @(#)tip.h 8.1 (Berkeley) 6/6/93 */ /* * tip - terminal interface program */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#ifndef EXTERN +#define EXTERN extern +#endif + /* * Remote host attributes */ -char *DV; /* UNIX device(s) to open */ -char *EL; /* chars marking an EOL */ -char *CM; /* initial connection message */ -char *IE; /* EOT to expect on input */ -char *OE; /* EOT to send to complete FT */ -char *CU; /* call unit if making a phone call */ -char *AT; /* acu type */ -char *PN; /* phone number(s) */ -char *DI; /* disconnect string */ -char *PA; /* parity to be generated */ +EXTERN char *DV; /* UNIX device(s) to open */ +EXTERN char *EL; /* chars marking an EOL */ +EXTERN char *CM; /* initial connection message */ +EXTERN char *IE; /* EOT to expect on input */ +EXTERN char *OE; /* EOT to send to complete FT */ +EXTERN char *CU; /* call unit if making a phone call */ +EXTERN char *AT; /* acu type */ +EXTERN char *PN; /* phone number(s) */ +EXTERN char *DI; /* disconnect string */ +EXTERN char *PA; /* parity to be generated */ -char *PH; /* phone number file */ -char *RM; /* remote file name */ -char *HO; /* host name */ +EXTERN char *PH; /* phone number file */ +EXTERN char *RM; /* remote file name */ +EXTERN char *HO; /* host name */ -long BR; /* line speed for conversation */ -long FS; /* frame size for transfers */ +EXTERN long BR; /* line speed for conversation */ +EXTERN long FS; /* frame size for transfers */ -short DU; /* this host is dialed up */ -short HW; /* this device is hardwired, see hunt.c */ -char *ES; /* escape character */ -char *EX; /* exceptions */ -char *FO; /* force (literal next) char*/ -char *RC; /* raise character */ -char *RE; /* script record file */ -char *PR; /* remote prompt */ -long DL; /* line delay for file transfers to remote */ -long CL; /* char delay for file transfers to remote */ -long ET; /* echocheck timeout */ -long LD; /* line disc */ -short HD; /* this host is half duplex - do local echo */ +EXTERN short DU; /* this host is dialed up */ +EXTERN short HW; /* this device is hardwired, see hunt.c */ +EXTERN char *ES; /* escape character */ +EXTERN char *EX; /* exceptions */ +EXTERN char *FO; /* force (literal next) char*/ +EXTERN char *RC; /* raise character */ +EXTERN char *RE; /* script record file */ +EXTERN char *PR; /* remote prompt */ +EXTERN long DL; /* line delay for file transfers to remote */ +EXTERN long CL; /* char delay for file transfers to remote */ +EXTERN long ET; /* echocheck timeout */ +EXTERN long LD; /* line disc */ +EXTERN short HD; /* this host is half duplex - do local echo */ /* * String value table */ typedef struct { char *v_name; /* whose name is it */ char v_type; /* for interpreting set's */ char v_access; /* protection of touchy ones */ char *v_abrev; /* possible abbreviation */ char *v_value; /* casted to a union later */ } value_t; #define STRING 01 /* string valued */ #define BOOL 02 /* true-false value */ #define NUMBER 04 /* numeric value */ #define CHAR 010 /* character value */ #define WRITE 01 /* write access to variable */ #define READ 02 /* read access */ #define CHANGED 01 /* low bit is used to show modification */ #define PUBLIC 1 /* public access rights */ #define PRIVATE 03 /* private to definer */ #define ROOT 05 /* root defined */ #define TRUE 1 #define FALSE 0 #define ENVIRON 020 /* initialize out of the environment */ #define IREMOTE 040 /* initialize out of remote structure */ #define INIT 0100 /* static data space used for initialization */ #define TMASK 017 /* * Definition of ACU line description */ typedef struct { char *acu_name; int (*acu_dialer)(char *, char *); void (*acu_disconnect)(void); void (*acu_abort)(void); } acu_t; #define equal(a, b) (strcmp(a,b)==0)/* A nice function to string compare */ /* * variable manipulation stuff -- * if we defined the value entry in value_t, then we couldn't * initialize it in vars.c, so we cast it as needed to keep lint * happy. */ #define value(v) vtable[v].v_value #define lvalue(v) (long)vtable[v].v_value #define number(v) ((long)(v)) #define boolean(v) ((short)(long)(v)) #define character(v) ((char)(long)(v)) #define address(v) ((long *)(v)) #define setnumber(v,n) do { (v) = (char *)(long)(n); } while (0) #define setboolean(v,n) do { (v) = (char *)(long)(n); } while (0) #define setcharacter(v,n) do { (v) = (char *)(long)(n); } while (0) #define setaddress(v,n) do { (v) = (char *)(n); } while (0) /* * Escape command table definitions -- * lookup in this table is performed when ``escapec'' is recognized * at the beginning of a line (as defined by the eolmarks variable). */ typedef struct { char e_char; /* char to match on */ char e_flags; /* experimental, privileged */ char *e_help; /* help string */ void (*e_func)(int); /* command */ } esctable_t; #define NORM 00 /* normal protection, execute anyone */ #define EXP 01 /* experimental, mark it with a `*' on help */ #define PRIV 02 /* privileged, root execute only */ extern int vflag; /* verbose during reading of .tiprc file */ extern int noesc; /* no escape `~' char */ extern value_t vtable[]; /* variable table */ #ifndef ACULOG #define logent(a, b, c, d) #define loginit() #endif /* * Definition of indices into variable table so * value(DEFINE) turns into a static address. */ #define BEAUTIFY 0 #define BAUDRATE 1 #define DIALTIMEOUT 2 #define EOFREAD 3 #define EOFWRITE 4 #define EOL 5 #define ESCAPE 6 #define EXCEPTIONS 7 #define FORCE 8 #define FRAMESIZE 9 #define HOST 10 #define LOG 11 #define PHONES 12 #define PROMPT 13 #define RAISE 14 #define RAISECHAR 15 #define RECORD 16 #define REMOTE 17 #define SCRIPT 18 #define TABEXPAND 19 #define VERBOSE 20 #define SHELL 21 #define HOME 22 #define ECHOCHECK 23 #define DISCONNECT 24 #define TAND 25 #define LDELAY 26 #define CDELAY 27 #define ETIMEOUT 28 #define RAWFTP 29 #define HALFDUPLEX 30 #define LECHO 31 #define PARITY 32 #define HARDWAREFLOW 33 #define LINEDISC 34 #define DC 35 #define NOVAL ((value_t *)NULL) #define NOACU ((acu_t *)NULL) #define NOSTR ((char *)NULL) #define NOFILE ((FILE *)NULL) #define NOPWD ((struct passwd *)0) -struct termios term; /* current mode of terminal */ -struct termios defterm; /* initial mode of terminal */ -struct termios defchars; /* current mode with initial chars */ -int gotdefterm; +EXTERN struct termios term; /* current mode of terminal */ +EXTERN struct termios defterm; /* initial mode of terminal */ +EXTERN struct termios defchars; /* current mode with initial chars */ +EXTERN int gotdefterm; -FILE *fscript; /* FILE for scripting */ +EXTERN FILE *fscript; /* FILE for scripting */ -int fildes[2]; /* file transfer synchronization channel */ -int repdes[2]; /* read process sychronization channel */ -int FD; /* open file descriptor to remote host */ -int AC; /* open file descriptor to dialer (v831 only) */ -int vflag; /* print .tiprc initialization sequence */ -int noesc; /* no `~' escape char */ -int sfd; /* for ~< operation */ -pid_t tipin_pid; /* pid of tipin */ -pid_t tipout_pid; /* pid of tipout */ -uid_t uid, euid; /* real and effective user id's */ -gid_t gid, egid; /* real and effective group id's */ -int stop; /* stop transfer session flag */ -int quit; /* same; but on other end */ -int intflag; /* recognized interrupt */ -int stoprompt; /* for interrupting a prompt session */ -int timedout; /* ~> transfer timedout */ -int cumode; /* simulating the "cu" program */ -int bits8; /* terminal is 8-bit mode */ +EXTERN int fildes[2]; /* file transfer synchronization channel */ +EXTERN int repdes[2]; /* read process sychronization channel */ +EXTERN int FD; /* open file descriptor to remote host */ +EXTERN int AC; /* open file descriptor to dialer (v831 only) */ +EXTERN int vflag; /* print .tiprc initialization sequence */ +EXTERN int noesc; /* no `~' escape char */ +EXTERN int sfd; /* for ~< operation */ +EXTERN pid_t tipin_pid; /* pid of tipin */ +EXTERN pid_t tipout_pid; /* pid of tipout */ +EXTERN uid_t uid, euid; /* real and effective user id's */ +EXTERN gid_t gid, egid; /* real and effective group id's */ +EXTERN int stop; /* stop transfer session flag */ +EXTERN int quit; /* same; but on other end */ +EXTERN int intflag; /* recognized interrupt */ +EXTERN int stoprompt; /* for interrupting a prompt session */ +EXTERN int timedout; /* ~> transfer timedout */ +EXTERN int cumode; /* simulating the "cu" program */ +EXTERN int bits8; /* terminal is 8-bit mode */ #define STRIP_PAR (bits8 ? 0377 : 0177) -char fname[PATH_MAX]; /* file name buffer for ~< */ -char copyname[PATH_MAX]; /* file name buffer for ~> */ -char ccc; /* synchronization character */ -char *uucplock; /* name of lock file for uucp's */ +EXTERN char fname[PATH_MAX]; /* file name buffer for ~< */ +EXTERN char copyname[PATH_MAX]; /* file name buffer for ~> */ +EXTERN char ccc; /* synchronization character */ +EXTERN char *uucplock; /* name of lock file for uucp's */ -int odisc; /* initial tty line discipline */ +EXTERN int odisc; /* initial tty line discipline */ extern int disc; /* current tty discpline */ extern char *__progname; /* program name */ char *con(void); char *ctrl(char); char *expand(char *); char *getremote(char *); char *interp(char *); int any(int, char *); int biz22w_dialer(char *, char *); int biz22f_dialer(char *, char *); int biz31w_dialer(char *, char *); int biz31f_dialer(char *, char *); int cour_dialer(char *, char *); int df02_dialer(char *, char *); int df03_dialer(char *, char *); int dn_dialer(char *, char *); int hay_dialer(char *, char *); int prompt(char *, char *, size_t); size_t size(char *); int t3000_dialer(char *, char *); int ttysetup(int); int uu_lock(char *); int uu_unlock(char *); int v3451_dialer(char *, char *); int v831_dialer(char *, char *); int ven_dialer(char *, char *); int vstring(char *, char *); long hunt(char *); void biz22_disconnect(void); void biz22_abort(void); void biz31_disconnect(void); void biz31_abort(void); void chdirectory(int); void cleanup(int); void consh(int); void cour_abort(void); void cour_disconnect(void); void cu_put(int); void cu_take(int); void cumain(int, char **); void daemon_uid(void); void df_abort(void); void df_disconnect(void); void disconnect(char *); void dn_abort(void); void dn_disconnect(void); void finish(int); void genbrk(int); void getfl(int); void hay_abort(void); void hay_disconnect(void); void help(int); void listvariables(int); void logent(char *, char *, char *, char *); void loginit(void); void parwrite(int, char *, size_t); void pipefile(int); void pipeout(int); void raw(void); void sendfile(int); void setparity(char *); void setscript(void); void shell(int); void shell_uid(void); void suspend(int); void t3000_disconnect(void); void t3000_abort(void); void timeout(int); void tipabort(char *); void tipout(void); void user_uid(void); void unexcl(void); void unraw(void); void v3451_abort(void); void v3451_disconnect(void); void v831_disconnect(void); void v831_abort(void); void variable(int); void ven_disconnect(void); void ven_abort(void); void vinit(void); void vlex(char *);