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

Defined functions

glocknf defined in line 340; used 1 times
gunlocknf defined in line 387; used 1 times
len defined in line 400; never used
listconv defined in line 513; used 2 times
listget defined in line 486; used 2 times
substr defined in line 606; used 2 times
tolcase defined in line 531; used 4 times
watchkid defined in line 167; used 2 times
x defined in line 192; used 184 times

Defined variables

kidpid defined in line 31; used 4 times
kidstatus defined in line 32; used 3 times
mnames defined in line 545; used 8 times
rcsid defined in line 11; never used

Defined macros

FORKTRY defined in line 15; used 1 times
  • in line 68
LOCKTRY defined in line 14; used 2 times
Last modified: 1996-03-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5044
Valid CSS Valid XHTML 1.0 Strict