1: #include <pwd.h>
   2: #include <time.h>
   3: #include "sendmail.h"
   4: #include <sys/stat.h>
   5: 
   6: SCCSID(@(#)envelope.c	4.2		8/21/83);
   7: 
   8: /*
   9: **  NEWENVELOPE -- allocate a new envelope
  10: **
  11: **	Supports inheritance.
  12: **
  13: **	Parameters:
  14: **		e -- the new envelope to fill in.
  15: **
  16: **	Returns:
  17: **		e.
  18: **
  19: **	Side Effects:
  20: **		none.
  21: */
  22: 
  23: ENVELOPE *
  24: newenvelope(e)
  25:     register ENVELOPE *e;
  26: {
  27:     register HDR *bh;
  28:     register HDR **nhp;
  29:     register ENVELOPE *parent;
  30:     extern putheader(), putbody();
  31:     extern ENVELOPE BlankEnvelope;
  32: 
  33:     parent = CurEnv;
  34:     if (e == CurEnv)
  35:         parent = e->e_parent;
  36:     clear((char *) e, sizeof *e);
  37:     bmove((char *) &CurEnv->e_from, (char *) &e->e_from, sizeof e->e_from);
  38:     e->e_parent = parent;
  39:     e->e_ctime = curtime();
  40:     e->e_puthdr = putheader;
  41:     e->e_putbody = putbody;
  42:     bh = BlankEnvelope.e_header;
  43:     nhp = &e->e_header;
  44:     while (bh != NULL)
  45:     {
  46:         *nhp = (HDR *) xalloc(sizeof *bh);
  47:         bmove((char *) bh, (char *) *nhp, sizeof *bh);
  48:         bh = bh->h_link;
  49:         nhp = &(*nhp)->h_link;
  50:     }
  51:     if (CurEnv->e_xfp != NULL)
  52:         (void) fflush(CurEnv->e_xfp);
  53: 
  54:     return (e);
  55: }
  56: /*
  57: **  DROPENVELOPE -- deallocate an envelope.
  58: **
  59: **	Parameters:
  60: **		e -- the envelope to deallocate.
  61: **
  62: **	Returns:
  63: **		none.
  64: **
  65: **	Side Effects:
  66: **		housekeeping necessary to dispose of an envelope.
  67: **		Unlocks this queue file.
  68: */
  69: 
  70: dropenvelope(e)
  71:     register ENVELOPE *e;
  72: {
  73:     bool queueit = FALSE;
  74:     register ADDRESS *q;
  75: 
  76: #ifdef DEBUG
  77:     if (tTd(50, 1))
  78:     {
  79:         printf("dropenvelope %x id=", e);
  80:         xputs(e->e_id);
  81:         printf(" flags=%o\n", e->e_flags);
  82:     }
  83: #endif DEBUG
  84: #ifdef LOG
  85:     if (LogLevel > 10)
  86:         syslog(LOG_DEBUG, "dropenvelope, id=%s, flags=%o, pid=%d",
  87:                   e->e_id == NULL ? "(none)" : e->e_id,
  88:                   e->e_flags, getpid());
  89: #endif LOG
  90: 
  91:     /* we must have an id to remove disk files */
  92:     if (e->e_id == NULL)
  93:         return;
  94: 
  95:     /*
  96: 	**  Extract state information from dregs of send list.
  97: 	*/
  98: 
  99:     for (q = e->e_sendqueue; q != NULL; q = q->q_next)
 100:     {
 101:         if (bitset(QQUEUEUP, q->q_flags))
 102:             queueit = TRUE;
 103:     }
 104: 
 105:     /*
 106: 	**  Send back return receipts as requested.
 107: 	*/
 108: 
 109:     if (e->e_receiptto != NULL && bitset(EF_SENDRECEIPT, e->e_flags))
 110:     {
 111:         auto ADDRESS *rlist = NULL;
 112: 
 113:         sendtolist(CurEnv->e_receiptto, (ADDRESS *) NULL, &rlist);
 114:         (void) returntosender("Return receipt", rlist, FALSE);
 115:     }
 116: 
 117:     /*
 118: 	**  Arrange to send error messages if there are fatal errors.
 119: 	*/
 120: 
 121:     if (bitset(EF_FATALERRS|EF_TIMEOUT, e->e_flags) && ErrorMode != EM_QUIET)
 122:         savemail(e);
 123: 
 124:     /*
 125: 	**  Instantiate or deinstantiate the queue.
 126: 	*/
 127: 
 128:     if ((!queueit && !bitset(EF_KEEPQUEUE, e->e_flags)) ||
 129:         bitset(EF_CLRQUEUE, e->e_flags))
 130:     {
 131:         if (e->e_dfp != NULL)
 132:             (void) fclose(e->e_dfp);
 133:         if (e->e_df != NULL)
 134:             xunlink(e->e_df);
 135:         xunlink(queuename(e, 'q'));
 136:     }
 137:     else if (queueit || !bitset(EF_INQUEUE, e->e_flags))
 138:     {
 139: #ifdef QUEUE
 140:         queueup(e, FALSE, FALSE);
 141: #else QUEUE
 142:         syserr("dropenvelope: queueup");
 143: #endif QUEUE
 144:     }
 145: 
 146:     /* now unlock the job */
 147:     closexscript(e);
 148:     unlockqueue(e);
 149: 
 150:     /* make sure that this envelope is marked unused */
 151:     e->e_id = e->e_df = NULL;
 152:     e->e_dfp = NULL;
 153: }
 154: /*
 155: **  CLEARENVELOPE -- clear an envelope without unlocking
 156: **
 157: **	This is normally used by a child process to get a clean
 158: **	envelope without disturbing the parent.
 159: **
 160: **	Parameters:
 161: **		e -- the envelope to clear.
 162: **
 163: **	Returns:
 164: **		none.
 165: **
 166: **	Side Effects:
 167: **		Closes files associated with the envelope.
 168: **		Marks the envelope as unallocated.
 169: */
 170: 
 171: clearenvelope(e)
 172:     register ENVELOPE *e;
 173: {
 174:     /* clear out any file information */
 175:     if (e->e_xfp != NULL)
 176:         (void) fclose(e->e_xfp);
 177:     if (e->e_dfp != NULL)
 178:         (void) fclose(e->e_dfp);
 179:     e->e_xfp = e->e_dfp = NULL;
 180: 
 181:     /* now expunge names of objects */
 182:     e->e_df = e->e_id = NULL;
 183: 
 184:     /* and the flags which are now meaningless */
 185:     e->e_flags = 0;
 186: }
 187: /*
 188: **  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
 189: **
 190: **	Parameters:
 191: **		e -- the envelope to unlock.
 192: **
 193: **	Returns:
 194: **		none
 195: **
 196: **	Side Effects:
 197: **		unlocks the queue for `e'.
 198: */
 199: 
 200: unlockqueue(e)
 201:     ENVELOPE *e;
 202: {
 203:     /* remove the transcript */
 204: #ifdef DEBUG
 205: # ifdef LOG
 206:     if (LogLevel > 19)
 207:         syslog(LOG_DEBUG, "%s: unlock", e->e_id);
 208: # endif LOG
 209:     if (!tTd(51, 4))
 210: #endif DEBUG
 211:         xunlink(queuename(e, 'x'));
 212: 
 213: # ifdef QUEUE
 214:     /* last but not least, remove the lock */
 215:     xunlink(queuename(e, 'l'));
 216: # endif QUEUE
 217: }
 218: /*
 219: **  INITSYS -- initialize instantiation of system
 220: **
 221: **	In Daemon mode, this is done in the child.
 222: **
 223: **	Parameters:
 224: **		none.
 225: **
 226: **	Returns:
 227: **		none.
 228: **
 229: **	Side Effects:
 230: **		Initializes the system macros, some global variables,
 231: **		etc.  In particular, the current time in various
 232: **		forms is set.
 233: */
 234: 
 235: initsys()
 236: {
 237:     static char cbuf[5];            /* holds hop count */
 238:     static char pbuf[10];           /* holds pid */
 239:     static char ybuf[10];           /* holds tty id */
 240:     register char *p;
 241:     extern char *ttyname();
 242:     extern char *macvalue();
 243:     extern char Version[];
 244: 
 245:     /*
 246: 	**  Give this envelope a reality.
 247: 	**	I.e., an id, a transcript, and a creation time.
 248: 	*/
 249: 
 250:     openxscript(CurEnv);
 251:     CurEnv->e_ctime = curtime();
 252: 
 253:     /*
 254: 	**  Set OutChannel to something useful if stdout isn't it.
 255: 	**	This arranges that any extra stuff the mailer produces
 256: 	**	gets sent back to the user on error (because it is
 257: 	**	tucked away in the transcript).
 258: 	*/
 259: 
 260:     if (OpMode == MD_DAEMON && QueueRun)
 261:         OutChannel = CurEnv->e_xfp;
 262: 
 263:     /*
 264: 	**  Set up some basic system macros.
 265: 	*/
 266: 
 267:     /* process id */
 268:     (void) sprintf(pbuf, "%d", getpid());
 269:     define('p', pbuf, CurEnv);
 270: 
 271:     /* hop count */
 272:     (void) sprintf(cbuf, "%d", CurEnv->e_hopcount);
 273:     define('c', cbuf, CurEnv);
 274: 
 275:     /* time as integer, unix time, arpa time */
 276:     settime();
 277: 
 278:     /* tty name */
 279:     if (macvalue('y', CurEnv) == NULL)
 280:     {
 281:         p = ttyname(2);
 282:         if (p != NULL)
 283:         {
 284:             if (rindex(p, '/') != NULL)
 285:                 p = rindex(p, '/') + 1;
 286:             (void) strcpy(ybuf, p);
 287:             define('y', ybuf, CurEnv);
 288:         }
 289:     }
 290: }
 291: /*
 292: **  SETTIME -- set the current time.
 293: **
 294: **	Parameters:
 295: **		none.
 296: **
 297: **	Returns:
 298: **		none.
 299: **
 300: **	Side Effects:
 301: **		Sets the various time macros -- $a, $b, $d, $t.
 302: */
 303: 
 304: settime()
 305: {
 306:     register char *p;
 307:     auto time_t now;
 308:     static char tbuf[20];           /* holds "current" time */
 309:     static char dbuf[30];           /* holds ctime(tbuf) */
 310:     register struct tm *tm;
 311:     extern char *arpadate();
 312:     extern struct tm *gmtime();
 313:     extern char *macvalue();
 314: 
 315:     now = curtime();
 316:     tm = gmtime(&now);
 317:     (void) sprintf(tbuf, "%02d%02d%02d%02d%02d", tm->tm_year, tm->tm_mon+1,
 318:             tm->tm_mday, tm->tm_hour, tm->tm_min);
 319:     define('t', tbuf, CurEnv);
 320:     (void) strcpy(dbuf, ctime(&now));
 321:     *index(dbuf, '\n') = '\0';
 322:     if (macvalue('d', CurEnv) == NULL)
 323:         define('d', dbuf, CurEnv);
 324:     p = newstr(arpadate(dbuf));
 325:     if (macvalue('a', CurEnv) == NULL)
 326:         define('a', p, CurEnv);
 327:     define('b', p, CurEnv);
 328: }
 329: /*
 330: **  QUEUENAME -- build a file name in the queue directory for this envelope.
 331: **
 332: **	Assigns an id code if one does not already exist.
 333: **	This code is very careful to avoid trashing existing files
 334: **	under any circumstances.
 335: **		We first create an nf file that is only used when
 336: **		assigning an id.  This file is always empty, so that
 337: **		we can never accidently truncate an lf file.
 338: **
 339: **	Parameters:
 340: **		e -- envelope to build it in/from.
 341: **		type -- the file type, used as the first character
 342: **			of the file name.
 343: **
 344: **	Returns:
 345: **		a pointer to the new file name (in a static buffer).
 346: **
 347: **	Side Effects:
 348: **		Will create the lf and qf files if no id code is
 349: **		already assigned.  This will cause the envelope
 350: **		to be modified.
 351: */
 352: 
 353: char *
 354: queuename(e, type)
 355:     register ENVELOPE *e;
 356:     char type;
 357: {
 358:     static char buf[MAXNAME];
 359:     static int pid = -1;
 360:     char c1 = 'A';
 361:     char c2 = 'A';
 362: 
 363:     if (e->e_id == NULL)
 364:     {
 365:         char qf[20];
 366:         char lf[20];
 367:         char nf[20];
 368: 
 369:         /* find a unique id */
 370:         if (pid != getpid())
 371:         {
 372:             /* new process -- start back at "AA" */
 373:             pid = getpid();
 374:             c1 = 'A';
 375:             c2 = 'A' - 1;
 376:         }
 377:         (void) sprintf(qf, "qfAA%05d", pid);
 378:         strcpy(lf, qf);
 379:         lf[0] = 'l';
 380:         strcpy(nf, qf);
 381:         nf[0] = 'n';
 382: 
 383:         while (c1 < '~' || c2 < 'Z')
 384:         {
 385:             int i;
 386: 
 387:             if (c2 >= 'Z')
 388:             {
 389:                 c1++;
 390:                 c2 = 'A' - 1;
 391:             }
 392:             qf[2] = lf[2] = nf[2] = c1;
 393:             qf[3] = lf[3] = nf[3] = ++c2;
 394: # ifdef DEBUG
 395:             if (tTd(7, 20))
 396:                 printf("queuename: trying \"%s\"\n", nf);
 397: # endif DEBUG
 398: # ifdef QUEUE
 399:             if (access(lf, 0) >= 0 || access(qf, 0) >= 0)
 400:                 continue;
 401:             errno = 0;
 402:             i = creat(nf, FileMode);
 403:             if (i < 0)
 404:             {
 405:                 (void) unlink(nf);  /* kernel bug */
 406:                 continue;
 407:             }
 408:             (void) close(i);
 409:             i = link(nf, lf);
 410:             (void) unlink(nf);
 411:             if (i < 0)
 412:                 continue;
 413:             if (link(lf, qf) >= 0)
 414:                 break;
 415:             (void) unlink(lf);
 416: # else QUEUE
 417:             if (close(creat(qf, FileMode)) < 0)
 418:                 continue;
 419: # endif QUEUE
 420:         }
 421:         if (c1 >= '~' && c2 >= 'Z')
 422:         {
 423:             syserr("queuename: Cannot create \"%s\" in \"%s\"",
 424:                 lf, QueueDir);
 425:             exit(EX_OSERR);
 426:         }
 427:         e->e_id = newstr(&qf[2]);
 428:         define('i', e->e_id, e);
 429: # ifdef DEBUG
 430:         if (tTd(7, 1))
 431:             printf("queuename: assigned id %s, env=%x\n", e->e_id, e);
 432: # ifdef LOG
 433:         if (LogLevel > 16)
 434:             syslog(LOG_DEBUG, "%s: assigned id", e->e_id);
 435: # endif LOG
 436: # endif DEBUG
 437:     }
 438: 
 439:     if (type == '\0')
 440:         return (NULL);
 441:     (void) sprintf(buf, "%cf%s", type, e->e_id);
 442: # ifdef DEBUG
 443:     if (tTd(7, 2))
 444:         printf("queuename: %s\n", buf);
 445: # endif DEBUG
 446:     return (buf);
 447: }
 448: /*
 449: **  OPENXSCRIPT -- Open transcript file
 450: **
 451: **	Creates a transcript file for possible eventual mailing or
 452: **	sending back.
 453: **
 454: **	Parameters:
 455: **		e -- the envelope to create the transcript in/for.
 456: **
 457: **	Returns:
 458: **		none
 459: **
 460: **	Side Effects:
 461: **		Creates the transcript file.
 462: */
 463: 
 464: openxscript(e)
 465:     register ENVELOPE *e;
 466: {
 467:     register char *p;
 468: 
 469: # ifdef LOG
 470:     if (LogLevel > 19)
 471:         syslog(LOG_DEBUG, "%s: openx%s", e->e_id, e->e_xfp == NULL ? "" : " (no)");
 472: # endif LOG
 473:     if (e->e_xfp != NULL)
 474:         return;
 475:     p = queuename(e, 'x');
 476:     e->e_xfp = fopen(p, "w");
 477:     if (e->e_xfp == NULL)
 478:         syserr("Can't create %s", p);
 479:     else
 480:         (void) chmod(p, 0644);
 481: }
 482: /*
 483: **  CLOSEXSCRIPT -- close the transcript file.
 484: **
 485: **	Parameters:
 486: **		e -- the envelope containing the transcript to close.
 487: **
 488: **	Returns:
 489: **		none.
 490: **
 491: **	Side Effects:
 492: **		none.
 493: */
 494: 
 495: closexscript(e)
 496:     register ENVELOPE *e;
 497: {
 498:     if (e->e_xfp == NULL)
 499:         return;
 500:     (void) fclose(e->e_xfp);
 501:     e->e_xfp = NULL;
 502: }
 503: /*
 504: **  SETSENDER -- set the person who this message is from
 505: **
 506: **	Under certain circumstances allow the user to say who
 507: **	s/he is (using -f or -r).  These are:
 508: **	1.  The user's uid is zero (root).
 509: **	2.  The user's login name is in an approved list (typically
 510: **	    from a network server).
 511: **	3.  The address the user is trying to claim has a
 512: **	    "!" character in it (since #2 doesn't do it for
 513: **	    us if we are dialing out for UUCP).
 514: **	A better check to replace #3 would be if the
 515: **	effective uid is "UUCP" -- this would require me
 516: **	to rewrite getpwent to "grab" uucp as it went by,
 517: **	make getname more nasty, do another passwd file
 518: **	scan, or compile the UID of "UUCP" into the code,
 519: **	all of which are reprehensible.
 520: **
 521: **	Assuming all of these fail, we figure out something
 522: **	ourselves.
 523: **
 524: **	Parameters:
 525: **		from -- the person we would like to believe this message
 526: **			is from, as specified on the command line.
 527: **
 528: **	Returns:
 529: **		none.
 530: **
 531: **	Side Effects:
 532: **		sets sendmail's notion of who the from person is.
 533: */
 534: 
 535: setsender(from)
 536:     char *from;
 537: {
 538:     register char **pvp;
 539:     register struct passwd *pw = NULL;
 540:     char *realname = NULL;
 541:     char buf[MAXNAME];
 542:     extern char *macvalue();
 543:     extern char **prescan();
 544:     extern bool safefile();
 545:     extern char *FullName;
 546: 
 547: # ifdef DEBUG
 548:     if (tTd(45, 1))
 549:         printf("setsender(%s)\n", from == NULL ? "" : from);
 550: # endif DEBUG
 551: 
 552:     /*
 553: 	**  Figure out the real user executing us.
 554: 	**	Username can return errno != 0 on non-errors.
 555: 	*/
 556: 
 557:     if (QueueRun || OpMode == MD_SMTP || OpMode == MD_ARPAFTP)
 558:         realname = from;
 559:     if (realname == NULL || realname[0] == '\0')
 560:     {
 561:         extern char *username();
 562: 
 563:         realname = username();
 564:         errno = 0;
 565:     }
 566:     if (realname == NULL || realname[0] == '\0')
 567:     {
 568:         extern struct passwd *getpwuid();
 569: 
 570:         pw = getpwuid(getruid());
 571:         if (pw != NULL)
 572:             realname = pw->pw_name;
 573:     }
 574:     if (realname == NULL || realname[0] == '\0')
 575:     {
 576:         syserr("Who are you?");
 577:         realname = "root";
 578:     }
 579: 
 580:     /*
 581: 	**  Determine if this real person is allowed to alias themselves.
 582: 	*/
 583: 
 584:     if (from != NULL)
 585:     {
 586:         extern bool trusteduser();
 587: 
 588:         if (!trusteduser(realname) &&
 589: # ifdef DEBUG
 590:             (!tTd(1, 9) || getuid() != geteuid()) &&
 591: # endif DEBUG
 592:             index(from, '!') == NULL && getuid() != 0)
 593:         {
 594:             /* network sends -r regardless (why why why?) */
 595:             /* syserr("%s, you cannot use the -f flag", realname); */
 596:             from = NULL;
 597:         }
 598:         else if (strcmp(from, realname) != 0)
 599:             pw = NULL;
 600:     }
 601: 
 602:     SuprErrs = TRUE;
 603:     if (from == NULL || parseaddr(from, &CurEnv->e_from, 1, '\0') == NULL)
 604:     {
 605:         from = newstr(realname);
 606:         (void) parseaddr(from, &CurEnv->e_from, 1, '\0');
 607:     }
 608:     else
 609:         FromFlag = TRUE;
 610:     CurEnv->e_from.q_flags |= QDONTSEND;
 611:     SuprErrs = FALSE;
 612: 
 613:     if (pw == NULL && CurEnv->e_from.q_mailer == LocalMailer)
 614:     {
 615:         extern struct passwd *getpwnam();
 616: 
 617:         pw = getpwnam(CurEnv->e_from.q_user);
 618:     }
 619: 
 620:     /*
 621: 	**  Process passwd file entry.
 622: 	*/
 623: 
 624:     if (pw != NULL)
 625:     {
 626:         /* extract home directory */
 627:         CurEnv->e_from.q_home = newstr(pw->pw_dir);
 628: 
 629:         /* extract user and group id */
 630:         CurEnv->e_from.q_uid = pw->pw_uid;
 631:         CurEnv->e_from.q_gid = pw->pw_gid;
 632: 
 633:         /* run user's .mailcf file */
 634:         define('z', CurEnv->e_from.q_home, CurEnv);
 635:         expand("$z/.mailcf", buf, &buf[sizeof buf - 1], CurEnv);
 636:         if (safefile(buf, getruid(), S_IREAD))
 637:             readcf(buf, FALSE);
 638: 
 639:         /* if the user has given fullname already, don't redefine */
 640:         if (FullName == NULL)
 641:             FullName = macvalue('x', CurEnv);
 642:         if (FullName != NULL && FullName[0] == '\0')
 643:             FullName = NULL;
 644: 
 645:         /* extract full name from passwd file */
 646:         if (FullName == NULL && pw->pw_gecos != NULL &&
 647:             strcmp(pw->pw_name, CurEnv->e_from.q_user) == 0)
 648:         {
 649:             buildfname(pw->pw_gecos, CurEnv->e_from.q_user, buf);
 650:             if (buf[0] != '\0')
 651:                 FullName = newstr(buf);
 652:         }
 653:         if (FullName != NULL)
 654:             define('x', FullName, CurEnv);
 655:     }
 656:     else
 657:     {
 658: #ifndef V6
 659:         if (CurEnv->e_from.q_home == NULL)
 660:             CurEnv->e_from.q_home = getenv("HOME");
 661: #endif V6
 662:         CurEnv->e_from.q_uid = getuid();
 663:         CurEnv->e_from.q_gid = getgid();
 664:     }
 665: 
 666:     if (CurEnv->e_from.q_uid != 0)
 667:     {
 668:         DefUid = CurEnv->e_from.q_uid;
 669:         DefGid = CurEnv->e_from.q_gid;
 670:     }
 671: 
 672:     /*
 673: 	**  Rewrite the from person to dispose of possible implicit
 674: 	**	links in the net.
 675: 	*/
 676: 
 677:     pvp = prescan(from, '\0');
 678:     if (pvp == NULL)
 679:     {
 680:         syserr("cannot prescan from (%s)", from);
 681:         finis();
 682:     }
 683:     rewrite(pvp, 3);
 684:     rewrite(pvp, 1);
 685:     rewrite(pvp, 4);
 686:     cataddr(pvp, buf, sizeof buf);
 687:     define('f', newstr(buf), CurEnv);
 688: 
 689:     /* save the domain spec if this mailer wants it */
 690:     if (bitnset(M_CANONICAL, CurEnv->e_from.q_mailer->m_flags))
 691:     {
 692:         extern char **copyplist();
 693: 
 694:         while (*pvp != NULL && strcmp(*pvp, "@") != 0)
 695:             pvp++;
 696:         if (*pvp != NULL)
 697:             CurEnv->e_fromdomain = copyplist(pvp, TRUE);
 698:     }
 699: }
 700: /*
 701: **  TRUSTEDUSER -- tell us if this user is to be trusted.
 702: **
 703: **	Parameters:
 704: **		user -- the user to be checked.
 705: **
 706: **	Returns:
 707: **		TRUE if the user is in an approved list.
 708: **		FALSE otherwise.
 709: **
 710: **	Side Effects:
 711: **		none.
 712: */
 713: 
 714: bool
 715: trusteduser(user)
 716:     char *user;
 717: {
 718:     register char **ulist;
 719:     extern char *TrustedUsers[];
 720: 
 721:     for (ulist = TrustedUsers; *ulist != NULL; ulist++)
 722:         if (strcmp(*ulist, user) == 0)
 723:             return (TRUE);
 724:     return (FALSE);
 725: }

Defined functions

clearenvelope defined in line 171; never used
closexscript defined in line 495; never used
dropenvelope defined in line 70; never used
openxscript defined in line 464; used 3 times
settime defined in line 304; used 2 times
trusteduser defined in line 714; used 2 times
unlockqueue defined in line 200; used 2 times
Last modified: 1983-12-09
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1771
Valid CSS Valid XHTML 1.0 Strict