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: }

Defined functions

glocknf defined in line 343; used 1 times
gunlocknf defined in line 390; used 1 times
len defined in line 403; never used
listconv defined in line 516; used 2 times
listget defined in line 489; used 2 times
substr defined in line 609; used 2 times
tolcase defined in line 534; used 4 times
watchkid defined in line 169; used 2 times
x defined in line 194; used 184 times

Defined variables

kidpid defined in line 32; used 4 times
kidstatus defined in line 33; used 3 times
mnames defined in line 548; used 8 times
rcsid defined in line 12; never used

Defined macros

FORKTRY defined in line 16; used 1 times
  • in line 69
LOCKTRY defined in line 15; used 2 times
Last modified: 1985-10-30
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1384
Valid CSS Valid XHTML 1.0 Strict