|
|
1.1 ! root 1: # ! 2: ! 3: #include "rcv.h" ! 4: #include <sys/stat.h> ! 5: ! 6: /* ! 7: * Mail -- a mail program ! 8: * ! 9: * Still more user commands. ! 10: */ ! 11: ! 12: /* ! 13: * Process a shell escape by saving signals, ignoring signals, ! 14: * and forking a sh -c ! 15: */ ! 16: ! 17: shell(str) ! 18: char *str; ! 19: { ! 20: int (*sig[2])(), stat[1]; ! 21: register int t; ! 22: char *Shell; ! 23: ! 24: if ((Shell = value("SHELL")) == NOSTR) ! 25: Shell = SHELL; ! 26: for (t = 2; t < 4; t++) ! 27: sig[t-2] = signal(t, SIG_IGN); ! 28: t = vfork(); ! 29: if (t == 0) { ! 30: for (t = 2; t < 4; t++) ! 31: if (sig[t-2] != SIG_IGN) ! 32: signal(t, SIG_DFL); ! 33: execl(Shell, Shell, "-c", str, 0); ! 34: perror(Shell); ! 35: _exit(1); ! 36: } ! 37: while (wait(stat) != t) ! 38: ; ! 39: if (t == -1) ! 40: perror("fork"); ! 41: for (t = 2; t < 4; t++) ! 42: signal(t, sig[t-2]); ! 43: printf("!\n"); ! 44: return(0); ! 45: } ! 46: ! 47: /* ! 48: * Fork an interactive shell. ! 49: */ ! 50: ! 51: dosh(str) ! 52: char *str; ! 53: { ! 54: int (*sig[2])(), stat[1]; ! 55: register int t; ! 56: char *Shell; ! 57: ! 58: if ((Shell = value("SHELL")) == NOSTR) ! 59: Shell = SHELL; ! 60: for (t = 2; t < 4; t++) ! 61: sig[t-2] = signal(t, SIG_IGN); ! 62: t = vfork(); ! 63: if (t == 0) { ! 64: for (t = 2; t < 4; t++) ! 65: if (sig[t-2] != SIG_IGN) ! 66: signal(t, SIG_DFL); ! 67: execl(Shell, Shell, 0); ! 68: perror(Shell); ! 69: _exit(1); ! 70: } ! 71: while (wait(stat) != t) ! 72: ; ! 73: if (t == -1) ! 74: perror("fork"); ! 75: for (t = 2; t < 4; t++) ! 76: signal(t, sig[t-2]); ! 77: putchar('\n'); ! 78: return(0); ! 79: } ! 80: ! 81: /* ! 82: * Print out a nice help message from some file or another. ! 83: */ ! 84: ! 85: help() ! 86: { ! 87: register c; ! 88: register FILE *f; ! 89: ! 90: if ((f = fopen(HELPFILE, "r")) == NULL) { ! 91: printf("No help just now.\n"); ! 92: return(1); ! 93: } ! 94: while ((c = getc(f)) != EOF) ! 95: putchar(c); ! 96: fclose(f); ! 97: return(0); ! 98: } ! 99: ! 100: /* ! 101: * Change user's working directory. ! 102: */ ! 103: ! 104: schdir(str) ! 105: char *str; ! 106: { ! 107: register char *cp; ! 108: ! 109: for (cp = str; *cp == ' '; cp++) ! 110: ; ! 111: if (*cp == '\0') ! 112: cp = homedir; ! 113: else ! 114: if ((cp = expand(cp)) == NOSTR) ! 115: return(1); ! 116: if (chdir(cp) < 0) { ! 117: perror(cp); ! 118: return(1); ! 119: } ! 120: return(0); ! 121: } ! 122: ! 123: /* ! 124: * Reply to a list of messages. Extract each name from the ! 125: * message header and send them off to mail1() ! 126: */ ! 127: ! 128: respond(msgvec) ! 129: int *msgvec; ! 130: { ! 131: struct message *mp; ! 132: char *cp, buf[2 * LINESIZE], *rcv; ! 133: struct name *np; ! 134: struct header head; ! 135: char *netmap(); ! 136: ! 137: if (msgvec[1] != 0) { ! 138: printf("Sorry, can't reply to multiple messages at once\n"); ! 139: return(1); ! 140: } ! 141: mp = &message[msgvec[0] - 1]; ! 142: dot = mp; ! 143: rcv = nameof(mp); ! 144: strcpy(buf, ""); ! 145: cp = hfield("to", mp); ! 146: if (cp != NOSTR) ! 147: strcpy(buf, cp); ! 148: np = elide(extract(buf, GTO)); ! 149: /* rcv = rename(rcv); */ ! 150: mapf(np, rcv); ! 151: np = delname(np, myname); ! 152: head.h_seq = 1; ! 153: cp = detract(np, 0); ! 154: if (cp != NOSTR) { ! 155: strcpy(buf, cp); ! 156: strcat(buf, " "); ! 157: strcat(buf, rcv); ! 158: } ! 159: else ! 160: strcpy(buf, rcv); ! 161: head.h_to = buf; ! 162: head.h_subject = hfield("subject", mp); ! 163: if (head.h_subject == NOSTR) ! 164: head.h_subject = hfield("subj", mp); ! 165: head.h_cc = NOSTR; ! 166: cp = hfield("cc", mp); ! 167: if (cp != NOSTR) { ! 168: np = elide(extract(cp, GCC)); ! 169: mapf(np, rcv); ! 170: np = delname(np, myname); ! 171: head.h_cc = detract(np, 0); ! 172: } ! 173: head.h_bcc = NOSTR; ! 174: mail1(&head); ! 175: return(0); ! 176: } ! 177: ! 178: /* ! 179: * Preserve the named messages, so that they will be sent ! 180: * back to the system mailbox. ! 181: */ ! 182: ! 183: preserve(msgvec) ! 184: int *msgvec; ! 185: { ! 186: register struct message *mp; ! 187: register int *ip, mesg; ! 188: ! 189: if (edit) { ! 190: printf("Cannot \"preserve\" in edit mode\n"); ! 191: return(1); ! 192: } ! 193: for (ip = msgvec; *ip != NULL; ip++) { ! 194: mesg = *ip; ! 195: mp = &message[mesg-1]; ! 196: mp->m_flag |= MPRESERVE; ! 197: dot = mp; ! 198: } ! 199: return(0); ! 200: } ! 201: ! 202: /* ! 203: * Print the size of each message. ! 204: */ ! 205: ! 206: messize(msgvec) ! 207: int *msgvec; ! 208: { ! 209: register struct message *mp; ! 210: register int *ip, mesg; ! 211: ! 212: for (ip = msgvec; *ip != NULL; ip++) { ! 213: mesg = *ip; ! 214: mp = &message[mesg-1]; ! 215: printf("%d: %d\n", mesg, msize(mp)); ! 216: } ! 217: return(0); ! 218: } ! 219: ! 220: /* ! 221: * Quit quickly. If we are sourcing, just pop the input level ! 222: * by returning an error. ! 223: */ ! 224: ! 225: rexit(e) ! 226: { ! 227: if (sourcing) ! 228: return(1); ! 229: exit(e); ! 230: } ! 231: ! 232: /* ! 233: * Set or display a variable value. Syntax is similar to that ! 234: * of csh. ! 235: */ ! 236: ! 237: set(arglist) ! 238: char **arglist; ! 239: { ! 240: register struct var *vp; ! 241: register char *cp, *cp2; ! 242: char varbuf[BUFSIZ], **ap, **p; ! 243: int errs, h, s; ! 244: ! 245: if (argcount(arglist) == 0) { ! 246: for (h = 0, s = 1; h < HSHSIZE; h++) ! 247: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) ! 248: s++; ! 249: ap = (char **) salloc(s * sizeof *ap); ! 250: for (h = 0, p = ap; h < HSHSIZE; h++) ! 251: for (vp = variables[h]; vp != NOVAR; vp = vp->v_link) ! 252: *p++ = vp->v_name; ! 253: *p = NOSTR; ! 254: sort(ap); ! 255: for (p = ap; *p != NOSTR; p++) ! 256: printf("%s\t%s\n", *p, value(*p)); ! 257: return(0); ! 258: } ! 259: errs = 0; ! 260: for (ap = arglist; *ap != NOSTR; ap++) { ! 261: cp = *ap; ! 262: cp2 = varbuf; ! 263: while (*cp != '=' && *cp != '\0') ! 264: *cp2++ = *cp++; ! 265: *cp2 = '\0'; ! 266: if (*cp == '\0') ! 267: cp = ""; ! 268: else ! 269: cp++; ! 270: if (equal(varbuf, "")) { ! 271: printf("Non-null variable name required\n"); ! 272: errs++; ! 273: continue; ! 274: } ! 275: assign(varbuf, cp); ! 276: } ! 277: return(errs); ! 278: } ! 279: ! 280: /* ! 281: * Unset a bunch of variable values. ! 282: */ ! 283: ! 284: unset(arglist) ! 285: char **arglist; ! 286: { ! 287: register struct var *vp, *vp2; ! 288: register char *cp; ! 289: int errs, h; ! 290: char **ap; ! 291: ! 292: errs = 0; ! 293: for (ap = arglist; *ap != NOSTR; ap++) { ! 294: if ((vp2 = lookup(*ap)) == NOVAR) { ! 295: if (!sourcing) { ! 296: printf("\"%s\": undefined variable\n", *ap); ! 297: errs++; ! 298: } ! 299: continue; ! 300: } ! 301: h = hash(*ap); ! 302: if (vp2 == variables[h]) { ! 303: variables[h] = variables[h]->v_link; ! 304: vfree(vp2->v_name); ! 305: vfree(vp2->v_value); ! 306: cfree(vp2); ! 307: continue; ! 308: } ! 309: for (vp = variables[h]; vp->v_link != vp2; vp = vp->v_link) ! 310: ; ! 311: vp->v_link = vp2->v_link; ! 312: vfree(vp2->v_name); ! 313: vfree(vp2->v_value); ! 314: cfree(vp2); ! 315: } ! 316: return(errs); ! 317: } ! 318: ! 319: /* ! 320: * Put add users to a group. ! 321: */ ! 322: ! 323: group(argv) ! 324: char **argv; ! 325: { ! 326: register struct grouphead *gh; ! 327: register struct group *gp; ! 328: register int h; ! 329: int s; ! 330: char **ap, *gname, **p; ! 331: ! 332: if (argcount(argv) == 0) { ! 333: for (h = 0, s = 1; h < HSHSIZE; h++) ! 334: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) ! 335: s++; ! 336: ap = (char **) salloc(s * sizeof *ap); ! 337: for (h = 0, p = ap; h < HSHSIZE; h++) ! 338: for (gh = groups[h]; gh != NOGRP; gh = gh->g_link) ! 339: *p++ = gh->g_name; ! 340: *p = NOSTR; ! 341: sort(ap); ! 342: for (p = ap; *p != NOSTR; p++) ! 343: printgroup(*p); ! 344: return(0); ! 345: } ! 346: if (argcount(argv) == 1) { ! 347: printgroup(*argv); ! 348: return(0); ! 349: } ! 350: gname = *argv; ! 351: h = hash(gname); ! 352: if ((gh = findgroup(gname)) == NOGRP) { ! 353: gh = (struct grouphead *) calloc(sizeof *gh, 1); ! 354: gh->g_name = vcopy(gname); ! 355: gh->g_list = NOGE; ! 356: gh->g_link = groups[h]; ! 357: groups[h] = gh; ! 358: } ! 359: ! 360: /* ! 361: * Insert names from the command list into the group. ! 362: * Who cares if there are duplicates? They get tossed ! 363: * later anyway. ! 364: */ ! 365: ! 366: for (ap = argv+1; *ap != NOSTR; ap++) { ! 367: gp = (struct group *) calloc(sizeof *gp, 1); ! 368: gp->ge_name = vcopy(*ap); ! 369: gp->ge_link = gh->g_list; ! 370: gh->g_list = gp; ! 371: } ! 372: return(0); ! 373: } ! 374: ! 375: /* ! 376: * Sort the passed string vecotor into ascending dictionary ! 377: * order. ! 378: */ ! 379: ! 380: sort(list) ! 381: char **list; ! 382: { ! 383: register char **ap; ! 384: int diction(); ! 385: ! 386: for (ap = list; *ap != NOSTR; ap++) ! 387: ; ! 388: if (ap-list < 2) ! 389: return; ! 390: qsort(list, ap-list, sizeof *list, diction); ! 391: } ! 392: ! 393: /* ! 394: * Do a dictionary order comparison of the arguments from ! 395: * qsort. ! 396: */ ! 397: ! 398: diction(a, b) ! 399: register char **a, **b; ! 400: { ! 401: return(strcmp(*a, *b)); ! 402: } ! 403: ! 404: /* ! 405: * The do nothing command for comments. ! 406: */ ! 407: ! 408: null(e) ! 409: { ! 410: return(0); ! 411: } ! 412: ! 413: /* ! 414: * Print out the current edit file, if we are editting. ! 415: * Otherwise, print the name of the person who's mail ! 416: * we are reading. ! 417: */ ! 418: ! 419: file(e) ! 420: { ! 421: register char *cp; ! 422: ! 423: if (edit) ! 424: printf("Reading \"%s\"\n", editfile); ! 425: else ! 426: printf("Reading %s's mail\n", rindex(mailname, '/') + 1); ! 427: return(0); ! 428: } ! 429: ! 430: /* ! 431: * Expand file names like echo ! 432: */ ! 433: ! 434: echo(argv) ! 435: char **argv; ! 436: { ! 437: register char **ap; ! 438: register char *cp; ! 439: ! 440: for (ap = argv; *ap != NOSTR; ap++) { ! 441: cp = *ap; ! 442: if ((cp = expand(cp)) != NOSTR) ! 443: printf("%s\n", cp); ! 444: } ! 445: return(0); ! 446: } ! 447: ! 448: /* ! 449: * Reply to a series of messages by simply mailing to the senders ! 450: * and not messing around with the To: and Cc: lists as in normal ! 451: * reply. ! 452: */ ! 453: ! 454: Respond(msgvec) ! 455: int msgvec[]; ! 456: { ! 457: struct header head; ! 458: struct message *mp; ! 459: register int s, *ap; ! 460: register char *cp, *subject; ! 461: ! 462: for (s = 0, ap = msgvec; *ap != 0; ap++) { ! 463: mp = &message[*ap - 1]; ! 464: dot = mp; ! 465: s += strlen(nameof(mp)) + 1; ! 466: } ! 467: if (s == 0) ! 468: return(0); ! 469: cp = salloc(s + 2); ! 470: head.h_to = cp; ! 471: for (ap = msgvec; *ap != 0; ap++) { ! 472: mp = &message[*ap - 1]; ! 473: cp = copy(nameof(mp), cp); ! 474: *cp++ = ' '; ! 475: } ! 476: *--cp = 0; ! 477: mp = &message[msgvec[0] - 1]; ! 478: subject = hfield("subject", mp); ! 479: head.h_seq = 0; ! 480: if (subject == NOSTR) ! 481: subject = hfield("subj", mp); ! 482: head.h_subject = subject; ! 483: if (subject != NOSTR) ! 484: head.h_seq++; ! 485: head.h_cc = NOSTR; ! 486: head.h_bcc = NOSTR; ! 487: mail1(&head); ! 488: return(0); ! 489: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.