Annotation of 43BSDTahoe/new/notes/src/misc.c, revision 1.1

1.1     ! root        1: #include <errno.h>
        !             2: #include <sys/param.h>
        !             3: #include "parms.h"
        !             4: #include "structs.h"
        !             5: #include <signal.h>                                    /* signal processing */
        !             6: #include <ctype.h>
        !             7: #ifdef SIGCHLD
        !             8: #include <sys/wait.h>                                  /* for child status */
        !             9: #endif SIGCHLD
        !            10: 
        !            11: #ifdef RCSIDENT
        !            12: static char rcsid[] = "$Header: misc.c,v 1.7.0.5 85/10/06 01:41:01 notes Rel $";
        !            13: #endif RCSIDENT
        !            14: 
        !            15: #define                LOCKTRY         10                      /* number of shots at grabbing */
        !            16: #define                FORKTRY         10                      /* tries at forking */
        !            17: 
        !            18: /*
        !            19:  * dounix(charstring, flag) will execute that character string as a shell command
        !            20:  * stolen from shell, though this one catches more signals.
        !            21:  *
        !            22:  *     Depending on the RUNSUID flag the routine sets things back to
        !            23:  *     the users group or uid. Early versions were setuid and newer
        !            24:  *     versions only run setgid.  Don't get confused by the "hisuid"
        !            25:  *     argument: it really means "reset to his permissions".
        !            26:  *     R. Kolstad -- 11/2/80
        !            27:  *     modified: R. Essick January 1982, to clean up some signal processing
        !            28:  *
        !            29:  */
        !            30: 
        !            31: #if    defined(SIGCHLD)
        !            32: static int  kidpid;                                    /* passed by kidwatch() */
        !            33: static  union wait kidstatus;
        !            34: #endif defined(SIGCHLD)
        !            35: 
        !            36: 
        !            37: #ifndef        FASTFORK
        !            38: dounix (linebuf, hisuid, ttymode)
        !            39: char    linebuf[];
        !            40: #else
        !            41: dounix (hisuid, ttymode, arg0, arg1, arg2, arg3, arg4)
        !            42: char   *arg0,
        !            43:        *arg1,
        !            44:        *arg2,
        !            45:        *arg3,
        !            46:        *arg4;
        !            47: #endif
        !            48: {
        !            49:     register    pid,
        !            50:                 forktry,
        !            51:                 rpid;
        !            52:     int     (*p) (),
        !            53:             (*q) (),
        !            54:             (*r) ();
        !            55: #if    defined(SIGTSTP)
        !            56:     int     (*s) ();
        !            57: #endif defined(SIGTSTP)
        !            58: #if    defined(SIGCHLD)
        !            59:     int     (*t) ();
        !            60:     extern int  watchkid ();                           /* catch stopped kids */
        !            61: #endif defined(SIGCHLD)
        !            62:     int     retcode;
        !            63: 
        !            64: 
        !            65:     if (ttymode)
        !            66:        ttystop ();                                     /* give back to normal mode */
        !            67:     pid = 0;                                           /* satisfy init conditions */
        !            68:     forktry = 0;                                       /* init the counter */
        !            69:     while (pid <= 0 && ++forktry < FORKTRY)
        !            70:     {
        !            71:        if ((pid = fork ()) == 0)
        !            72:        {
        !            73:            uncatchem ();                               /* reset this process signals */
        !            74:                                                        /* if user can get his hands on it */
        !            75:            if (hisuid)                                 /* only set uid if giving shell */
        !            76: #ifdef RUNSUID
        !            77:                setuid (globuid);                       /* give him his uid */
        !            78: #else
        !            79:            setgid (getgid ());                         /* his group */
        !            80: #endif RUNSUID
        !            81:            for (rpid = 3; rpid < NOFILE; rpid++)       /* close extra files */
        !            82:                close (rpid);
        !            83: 
        !            84: #ifndef        FASTFORK
        !            85:            if (linebuf == 0)
        !            86:                execl (hisshell, hisshell, 0);
        !            87:            else
        !            88:                execl (DFLTSH, "sh", "-c", linebuf, 0);
        !            89:            printf ("Rats -- Couldn't load %s\n", DFLTSH);
        !            90: #else
        !            91:            if (arg0 == 0)
        !            92:                execlp (hisshell, hisshell, 0);
        !            93:            else
        !            94:                execlp (arg0, arg0, arg1, arg2, arg3, arg4);
        !            95:            printf ("Rats - Couldn't load %s\n", arg0);
        !            96: #endif
        !            97: 
        !            98:            _exit (BAD);                                /* if exec fails .. */
        !            99:        }
        !           100:        if (pid <= 0)                                   /* if fork failed */
        !           101:            sleep (2);                                  /* wait a bit */
        !           102:     }
        !           103:     if (pid > 0)                                       /* only if have son */
        !           104:     {
        !           105:        p = signal (SIGHUP, SIG_IGN);
        !           106:        q = signal (SIGINT, SIG_IGN);
        !           107:        r = signal (SIGQUIT, SIG_IGN);
        !           108: #if    defined(SIGTSTP)
        !           109:        s = signal (SIGTSTP, SIG_DFL);
        !           110: #endif defined(SIGTSTP)
        !           111: #if    defined(SIGCHLD)
        !           112:        t = signal (SIGCHLD, watchkid);                 /* if he signals */
        !           113: #endif defined(SIGCHLD)
        !           114:        while ((rpid = wait (&retcode)) != pid && rpid != -1);
        !           115:        if (rpid == -1)
        !           116:        {
        !           117: #if    defined(SIGCHLD)
        !           118: /*
        !           119:  *     watchkid() might have sucked down the status of the terminated
        !           120:  *     child, so we load whatever value it left for us in kidstatus
        !           121:  *     (provided that kidpid was ok)
        !           122:  */
        !           123:            if (pid == kidpid)                          /* the one we wanted */
        !           124:                retcode = kidstatus.w_status;           /* from watchkid() */
        !           125:            else
        !           126:                retcode = 1 << 8;                       /* make an error */
        !           127: #else
        !           128: /*
        !           129:  *     normal case, if the wait() failed for some reason we say that it
        !           130:  *     is an error.
        !           131:  */
        !           132:            retcode = 1 << 8;                           /* indicates error  */
        !           133: #endif defined(SIGCHLD)
        !           134:        }
        !           135:        signal (SIGHUP, p);
        !           136:        signal (SIGINT, q);
        !           137:        signal (SIGQUIT, r);
        !           138: #if    defined(SIGTSTP)
        !           139:        signal (SIGTSTP, s);
        !           140: #endif defined(SIGTSTP)
        !           141: #if    defined(SIGCHLD)
        !           142:        signal (SIGCHLD, t);
        !           143: #endif defined(SIGCHLD)
        !           144:     }
        !           145:     else
        !           146:        retcode = -1;                                   /* some sort of error */
        !           147:     if (ttymode)
        !           148:        ttystrt ();                                     /* back into raw mode */
        !           149:     return retcode >> 8;                               /* hand him the completion code */
        !           150: }
        !           151: 
        !           152: #if    defined(SIGCHLD)
        !           153: /*
        !           154:  *     watchkid()
        !           155:  *
        !           156:  *     called when we receive a SIGCHLD signal, indicating that a child's
        !           157:  *     status has changed.  This routine looks via wait3() to see if
        !           158:  *     the children have merely been suspended.  If so, it stops itself
        !           159:  *     so that it's parent can decide what to do.
        !           160:  *
        !           161:  *     This catches problems with programs like vi which run in raw mode
        !           162:  *     and catch ^z as a character. They later try to signal the entire
        !           163:  *     process group but are unable to signal the notes process since it
        !           164:  *     has a different effective uid. By watching the SIGCHLD signal, we
        !           165:  *     get notification when the vi process has stopped and we can stop
        !           166:  *     ourselves. 
        !           167:  *                             Ray Essick,     Augst 22, 1984
        !           168:  */
        !           169: static int  watchkid (sig)
        !           170: int     sig;
        !           171: {
        !           172: 
        !           173:     kidpid = wait3 (&kidstatus, WUNTRACED | WNOHANG, 0);/* get status */
        !           174:     if (kidpid == 0)                                   /* nothing to report */
        !           175:        return 0;                                       /* get out */
        !           176:     if (kidpid == (-1))                                        /* no children at all */
        !           177:        return 0;                                       /* get out */
        !           178:     if (WIFSTOPPED (kidstatus))                                /* stopped himself */
        !           179:     {
        !           180:        kill (getpid (), SIGTSTP);                      /* stop myself */
        !           181:     }
        !           182: }
        !           183: #endif defined(SIGCHLD)
        !           184: 
        !           185: /*
        !           186:  *     If the condition is TRUE (non-zero) abort the program.
        !           187:  *
        !           188:  *     Print the supplied message and halt.
        !           189:  *     Leave an optional core dump for debugging later.
        !           190:  *
        !           191:  *     Ray Essick 10/23/80
        !           192:  */
        !           193: 
        !           194: x (cond, p) char   *p;
        !           195: {
        !           196:     if (cond == 0)
        !           197:        return;                                         /* didnt fail */
        !           198: 
        !           199:     perror ("notes");
        !           200:     fprintf (stderr, "Fatal Internal Notesfile Error: %s\n", p);
        !           201:     ttystop ();                                                /* back to normal */
        !           202: 
        !           203: 
        !           204: #ifdef DUMPCORE
        !           205:     if (chdir (Mstdir) < 0)                            /* go to known place */
        !           206:        exit (BAD);                                     /* drop out */
        !           207:     if (chdir (UTILITY) < 0)
        !           208:        exit (BAD);                                     /* drop out */
        !           209:     if (chdir (DUMPCORE) < 0)                          /* writeable to all */
        !           210:        exit (BAD);                                     /* drop out */
        !           211: #ifdef RUNSUID
        !           212:     setuid (globuid);                                  /* won't dump if euid != uid */
        !           213: #else
        !           214:     setgid (getgid ());                                        /* no gift groups */
        !           215: #endif RUNSUID
        !           216: #endif DUMPCORE
        !           217: 
        !           218: #ifdef NFMAINT
        !           219: /*
        !           220:  *     This code is kind of risky.  If the NFMAINT notesfile ever
        !           221:  *     gets trashed and starts calling this routine, look out because
        !           222:  *     it will recursively fail. This is the unfortunate byproduct
        !           223:  *     of the fact that the "x" routine doesn't know what the 
        !           224:  *     current notesfile is.
        !           225:  */
        !           226:     {
        !           227:        char    pbuf[512];                              /* hold message */
        !           228:        char    pbuf2[128];                             /* and title */
        !           229:        char    pbuf3[256];                             /* core image */
        !           230:        char   *tail;                                   /* end of invocation */
        !           231: 
        !           232:        sprintf (pbuf2, "%s: aborted", Invokedas);
        !           233:        sprintf (pbuf, "Program:\t%s\nMessage:\t%s\n\nerrno:\t\t%d  (%s)\n",
        !           234:                Invokedas, p, errno,
        !           235:                errno >= sys_nerr ? "Unknown error code" : sys_errlist[errno]);
        !           236: #ifdef DUMPCORE
        !           237:        if ((tail = rindex (Invokedas, '/')) == NULL)   /* pathname? */
        !           238:            tail = Invokedas;                           /* simple invocation */
        !           239:        else
        !           240:            tail++;                                     /* strip the slash */
        !           241:        sprintf (pbuf3, "%s/%s/%s/%s", Mstdir, UTILITY, DUMPCORE, tail);
        !           242:        nfabort (NFMAINT, pbuf, pbuf2, pbuf3, BAD);     /* log & abort */
        !           243: #else  ! DUMPCORE
        !           244:        nfcomment (NFMAINT, pbuf, pbuf2, 0, 0);         /* actual insertion */
        !           245: #endif DUMPCORE
        !           246:     }
        !           247: #endif NFMAINT
        !           248: 
        !           249: /*
        !           250:  *     Handle the exit if NFMAINT is undefined.
        !           251:  */
        !           252: 
        !           253: #ifdef DUMPCORE
        !           254:     abort ();                                          /* dump in "core" */
        !           255: #else
        !           256:     exit (BAD);                                                /* for production */
        !           257: #endif DUMPCORE
        !           258: }
        !           259: 
        !           260: /*
        !           261:  *     lock creates a lock file, or waits until it can create the lock.
        !           262:  *     lock files are of the form lock#  where # is a character passed
        !           263:  *     to the routine.
        !           264:  *
        !           265:  *     Rob Kolstad     10/20/80
        !           266:  *     modified: rbe December 1981 to add full path name for lock file 
        !           267:  */
        !           268: 
        !           269: locknf (io, c)
        !           270: struct io_f *io;
        !           271: char    c;
        !           272: {
        !           273:     register int    i,
        !           274:                     holderr,
        !           275:                     trys;
        !           276:     char    p[WDLEN];
        !           277: 
        !           278:     sprintf (p, "%s/%s/%c%s", Mstdir, LOCKS, c, io -> nf);
        !           279:                                                        /* generate file name */
        !           280:     trys = LOCKTRY;                                    /* set him up */
        !           281:     while ((i = creat (p, 0)) < 0)
        !           282:     {
        !           283:        if (trys-- == 0)
        !           284:        {
        !           285:            holderr = errno;                            /* before it's abused */
        !           286:            fprintf (stderr, "lock %c (%s) permanently locked - consult a guru\n",
        !           287:                    c, io -> nf);
        !           288: #ifdef NFMAINT
        !           289:            if (strcmp (NFMAINT, io -> nf))             /* avoid loops */
        !           290:            {
        !           291:                char    pbuf[256];                      /* for error logging */
        !           292:                char    tbuf[256];                      /* title */
        !           293:                sprintf (pbuf,
        !           294:                        "lock %c failed for %s,\nerrno = %d (%s)\nProgram = %s\n",
        !           295:                        c, io -> fullname, holderr, sys_errlist[holderr],
        !           296:                        Invokedas);
        !           297:                sprintf (tbuf, "%s: locked (%c)", io -> nf, c);
        !           298:                nfcomment (NFMAINT, pbuf, tbuf, 0, 0);
        !           299:            }
        !           300: #endif NFMAINT
        !           301:            ttystop ();
        !           302:            exit (BAD);
        !           303:        }
        !           304:        sleep (2);                                      /* guarantee at least 1 */
        !           305:     }
        !           306:     ignoresigs++;                                      /* critical section */
        !           307: /*
        !           308:  *     could be above getting the lock, but wanted to be able to suspend
        !           309:  *     while getting the lock.  The interuptable window is very small
        !           310:  */
        !           311:     close (i);
        !           312: }
        !           313: 
        !           314: /*
        !           315:  *     unlock takes the same arguements as the lock routine, and it
        !           316:  *     will remove the corresponding lock file
        !           317:  *
        !           318:  *     Rob Kolstad 10/20/80
        !           319:  *     modified: rbe December 1981 to add full path name for lock name
        !           320:  */
        !           321: 
        !           322: unlocknf (io, c)
        !           323: struct io_f *io;
        !           324: char    c;
        !           325: {
        !           326:     char    p[WDLEN];
        !           327: 
        !           328:     sprintf (p, "%s/%s/%c%s", Mstdir, LOCKS, c, io -> nf);
        !           329:                                                        /* generate file name */
        !           330:     x (unlink (p) < 0, "unlock: unlink lock");
        !           331:     ignoresigs--;                                      /* no longer critical */
        !           332: }
        !           333: 
        !           334: /*
        !           335:  *     glock creates a lock file, or waits until it can create the lock.
        !           336:  *     lock files are of the form lock#  where # is a character passed
        !           337:  *     to the routine.
        !           338:  *             This lock file is a GLOBAL lock - across all notefiles
        !           339:  *
        !           340:  *     taken from lock routine above by R. Essick December 1981
        !           341:  */
        !           342: 
        !           343: glocknf (io, c)
        !           344: struct io_f *io;                                       /* unused in this routine */
        !           345: char    c;
        !           346: {
        !           347:     register int    i,
        !           348:                     holderr,
        !           349:                     trys;
        !           350:     char    p[WDLEN];
        !           351: 
        !           352:     sprintf (p, "%s/%s/%c", Mstdir, LOCKS, c);         /* generate file name */
        !           353:     trys = LOCKTRY;
        !           354:     while ((i = creat (p, 0)) < 0)
        !           355:     {
        !           356:        if (trys-- == 0)
        !           357:        {
        !           358:            holderr = errno;                            /* before it's abused */
        !           359:            fprintf (stderr, "lock%c combo lost - consult your local guru\n", c);
        !           360: #ifdef NFMAINT
        !           361:            if (strcmp (NFMAINT, io -> nf))             /* don't loop on self */
        !           362:            {
        !           363:                char    pbuf[256];                      /* for error logging */
        !           364:                char    pbuf2[256];
        !           365:                sprintf (pbuf,
        !           366:                        "glock %c failed for %s, errno = %d (%s)\nProgram = %s\n",
        !           367:                        c, io -> fullname, holderr, sys_errlist[holderr],
        !           368:                        Invokedas);
        !           369:                sprintf (pbuf2, "Frozen Global Lock (%c)", c);
        !           370:                nfcomment (NFMAINT, pbuf, pbuf2, 0, 0);
        !           371:            }
        !           372: #endif NFMAINT
        !           373:            ttystop ();
        !           374:            exit (BAD);
        !           375:        }
        !           376:        sleep (2);                                      /* is there a smaller time interval */
        !           377:     }
        !           378:     close (i);
        !           379: }
        !           380: 
        !           381: /*
        !           382:  *     gunlock takes the same arguements as the lock routine, and it
        !           383:  *     will remove the corresponding lock file
        !           384:  *             This is GLOBAL locking - across all notefiles
        !           385:  *
        !           386:  *     copy of code from unlock, with minor changes
        !           387:  *     Ray Essick      December 1981
        !           388:  */
        !           389: 
        !           390: gunlocknf (io, c)
        !           391: struct io_f *io;                                       /* not used by this routine */
        !           392: char    c;
        !           393: {
        !           394:     char    p[WDLEN];
        !           395: 
        !           396:     sprintf (p, "%s/%s/%c", Mstdir, LOCKS, c);         /* make the file name */
        !           397:     x (unlink (p) < 0, "gunlock: unlink lock");
        !           398: }
        !           399: 
        !           400: /*
        !           401:  * length tells us max(length of string, 1)
        !           402:  */
        !           403: len (p, n) char *p;
        !           404: {
        !           405:     int     i;
        !           406:     i = n;
        !           407:     p += n;
        !           408:     while (*--p == ' ' && --i)
        !           409:        if (i == 0)
        !           410:            i = 1;
        !           411:     return i;
        !           412: }
        !           413: 
        !           414: /*
        !           415:  *     shell - give the user a shell
        !           416:  *     this includes:
        !           417:  *     1) changing to the directory where he came in from
        !           418:  *     2) giving him a shell
        !           419:  *     3) return to the notefile directory
        !           420:  *
        !           421:  *     original author: Ray Essick may 29, 1981
        !           422:  *
        !           423:  */
        !           424: 
        !           425: gshell ()
        !           426: {
        !           427:     printf ("\n");
        !           428: #ifndef        FASTFORK
        !           429:     dounix (0, 1, 1);                                  /* give him his shell */
        !           430: #else
        !           431:     dounix (1, 1, 0, 0, 0, 0, 0);
        !           432: #endif
        !           433:     return 0;
        !           434: }
        !           435: 
        !           436: /*     copydate merely moves a when_f structure from 'from' to 'to' */
        !           437: /*     ray essick - 20-nov-1981        */
        !           438: 
        !           439: copydate (from, to)
        !           440: struct when_f  *from,
        !           441:                *to;
        !           442: {
        !           443:     *to = *from;                                       /* use block move */
        !           444: }
        !           445: 
        !           446: /*     strmove - copy a null terminated string to another */
        !           447: /*     returns the count of characters moved, this count includes the */
        !           448: /*     null terminator.. */
        !           449: /*     r. essick 20-nov-81 */
        !           450: 
        !           451: strmove (p, q)
        !           452: char   *p,
        !           453:        *q;                                             /* from p to q */
        !           454: {
        !           455:     int     count;
        !           456:     register char  *pp,
        !           457:                    *qq;
        !           458: 
        !           459:     count = 0;                                         /* start with no characters moved */
        !           460:     pp = p;
        !           461:     qq = q;                                            /* use registers for speed */
        !           462:     while (*qq++ = *pp++)
        !           463:        count++;
        !           464:     return count;                                      /* return count of characters moved */
        !           465:                                                        /* don't include the terminator */
        !           466: }
        !           467: 
        !           468: /*     copyauth(from, to) struct auth_f *from,*auth
        !           469:  *     copys author from from to to
        !           470:  *     Ray Essick December 1981
        !           471:  *
        !           472:  *     SHOULD USE STRUCTURE ASSIGNMENT IN ALL PLACES THAT CALL THIS
        !           473:  */
        !           474: copyauth (from, to)
        !           475: struct auth_f  *from,
        !           476:                *to;
        !           477: {
        !           478: 
        !           479:     strncpy (to -> aname, from -> aname, NAMESZ);      /* author name */
        !           480:     strncpy (to -> asystem, from -> asystem, HOMESYSSZ);/* home machine */
        !           481:     to -> aid = from -> aid;                           /* and user id */
        !           482: }
        !           483: 
        !           484: /*     listget, listconv - parse a list of numbers. 
        !           485:  *     this is all taken ( sort of ) from Rob Kolstad's getpg
        !           486:  *     program 
        !           487:  */
        !           488: 
        !           489: listget (buf, ptr, start, finish)
        !           490: char    buf[];
        !           491: int    *ptr,
        !           492:        *start,
        !           493:        *finish;
        !           494: {
        !           495:     if ((buf[*ptr] < '0' || buf[*ptr] > '9') && buf[*ptr] != ' ')
        !           496:     {
        !           497:        return 0;                                       /* end of this list */
        !           498:     }
        !           499:     *start = listconv (buf, ptr);                      /* get the first */
        !           500:     *finish = *start;                                  /* default to single */
        !           501:     if (buf[*ptr] == '-')
        !           502:     {
        !           503:        ++(*ptr);                                       /* trash that separator */
        !           504:        *finish = listconv (buf, ptr);                  /* grab second */
        !           505:        ++(*ptr);                                       /* bump past delimiter */
        !           506:        return 2;                                       /* parsed 2 arguements */
        !           507:     }
        !           508:     else
        !           509:     {
        !           510:        if (buf[*ptr] != '\0')
        !           511:            ++(*ptr);                                   /* dump delimiter */
        !           512:        return 1;
        !           513:     }
        !           514: }
        !           515: 
        !           516: listconv (buf, ptr)
        !           517: char    buf[];
        !           518: int    *ptr;
        !           519: {
        !           520:     int     i;
        !           521:     i = 0;
        !           522:     while (buf[*ptr] == ' ')
        !           523:        ++(*ptr);
        !           524:     while (buf[*ptr] >= '0' && buf[*ptr] <= '9')
        !           525:     {
        !           526:        i = 10 * i + buf[*ptr] - '0';
        !           527:        ++(*ptr);                                       /* bump him */
        !           528:     }
        !           529:     return (i);
        !           530: }
        !           531: 
        !           532: /*     tolcase - check to see if upper case, and convert to lcase */
        !           533: /*     R. Essick       Feb 1982 */
        !           534: tolcase (c)
        !           535: char    c;
        !           536: {
        !           537:     if (isascii (c) && isupper (c))
        !           538:        return (tolower (c));                           /* to lower case */
        !           539:     return (c);                                                /* leave as is */
        !           540: }
        !           541: 
        !           542: /*
        !           543:  *     Date printing stuff.
        !           544:  *
        !           545:  *     CHANGE TO CTIME(III) FORMAT EVENTUALLY
        !           546:  */
        !           547: 
        !           548: char   *mnames[13] =                                   /* so indexes work right */
        !           549: {
        !           550:     "???", "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug",
        !           551:     "Sep", "Oct", "Nov", "Dec"
        !           552: };
        !           553: 
        !           554: sprdate (w, str) struct when_f *w;
        !           555: char   *str;
        !           556: {
        !           557:     char   *m;
        !           558:     int     h,
        !           559:             i,
        !           560:             j;                                         /* temps to print 0's or funny strings */
        !           561:     m = "am";
        !           562:     h = w -> w_hours;
        !           563:     if (h >= 12)
        !           564:        m = "pm";
        !           565:     if (h == 0)
        !           566:        h = 12;
        !           567:     if (h > 12)
        !           568:        h -= 12;
        !           569:     i = w -> w_mins / 10;
        !           570:     j = w -> w_mins % 10;                              /* get those leading zeroes */
        !           571:     sprintf (str, "%2d:%d%d %2s  %3s %2d, %4d", h, i, j, m, mnames[w -> w_month], w -> w_day, w -> w_year);
        !           572:                                                        /* sprintf puts it into a string */
        !           573: }
        !           574: 
        !           575: prdate (zdate) struct when_f   *zdate;
        !           576: {
        !           577:     char    line[DATELEN];
        !           578: 
        !           579:     sprdate (zdate, line);                             /* format it */
        !           580:     printf ("%s", line);                               /* and print it */
        !           581: }
        !           582: 
        !           583: /*
        !           584:  *     Saves a string with malloc() and returns a pointer
        !           585:  *     to where it wound up.  Useful for building lists of
        !           586:  *     stuff.
        !           587:  *
        !           588:  *     Courtesy of Lou Salkind & Rick Spickelmier.
        !           589:  */
        !           590: 
        !           591: 
        !           592: char   *strsave (s)
        !           593: char   *s;
        !           594: {
        !           595:     char   *p;
        !           596:     extern char *malloc ();
        !           597: 
        !           598:     p = malloc (strlen (s) + 1);
        !           599:     strcpy (p, s);
        !           600:     return (p);
        !           601: }
        !           602: 
        !           603: /*
        !           604:  *     substr(a,b)     see if A is a substring of B
        !           605:  *
        !           606:  *     uses: strlen.
        !           607:  */
        !           608: 
        !           609: substr (a, b)
        !           610: char   *a;
        !           611: char   *b;
        !           612: {
        !           613:     register char   first;
        !           614:     register int    length;                            /* length of a */
        !           615:     register int    count;                             /* max checks */
        !           616: 
        !           617:     first = *a;                                                /* get first */
        !           618:     length = strlen (a);                               /* for strncmp */
        !           619:     count = strlen (b) - length + 1;                   /* max checks */
        !           620:     while (count-- > 0)                                        /* can try */
        !           621:     {
        !           622:        if (*b == first && !strncmp (a, b, length))
        !           623:            return (1);                                 /* is a substring */
        !           624:        b++;                                            /* on to next */
        !           625:     }
        !           626:     return (0);                                                /* not a substring */
        !           627: }
        !           628: 
        !           629: /*
        !           630:  *     routine to process a string and remove any
        !           631:  *     nasties like control characters and escape codes.
        !           632:  */
        !           633: 
        !           634: int     strclean (p)
        !           635: char   *p;
        !           636: {
        !           637:     if (p == (char *) NULL)
        !           638:        return 0;
        !           639:     if (*p == '\0')
        !           640:        return 0;
        !           641:     do
        !           642:     {
        !           643:        if (!isascii (*p) || iscntrl (*p))
        !           644:            *p = '_';                                   /* kill controls */
        !           645:     } while (*++p != '\0');
        !           646:     return (0);
        !           647: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.