/* * Sets/unsets an environment variable from a pointer that may actually be a * pointer into environ where the string should not be manipulated. */ static void change_env(char *s, int set) { char *eqp; char *ss; ss = savestr(s); if ((eqp = strchr(ss, '=')) != NULL) *eqp = '\0'; if (set && eqp != NULL) (void) setenv(ss, eqp + 1, 1); else (void) unsetenv(ss); ckfree(ss); return; }
static void tryexec(char *cmd, char **argv, char **envp) { int e; execve(cmd, argv, envp); e = errno; if (e == ENOEXEC) { initshellproc(); setinputfile(cmd, 0); commandname = arg0 = savestr(argv[0]); setparam(argv + 1); exraise(EXSHELLPROC); /*NOTREACHED*/ } errno = e; }
Screen_Obj *dup_so(QSP_ARG_DECL Screen_Obj *sop) { Screen_Obj *dup; char name[BUF_LEN]; sprintf(name,"%s.dup",SOB_NAME(sop)); dup = simple_object(name); if( sop == NULL ) return(sop); SET_SOB_PARENT(dup, SOB_PARENT(sop) ); SET_SOB_PANEL(dup, SOB_PANEL(sop) ); #ifdef HAVE_MOTIF SET_SOB_FRAME(dup, SOB_FRAME(sop) ); #endif /* HAVE_MOTIF */ SET_SOB_ACTION(dup,savestr(SOB_ACTION(sop))); SET_SOB_SELECTOR(dup,NULL); return(dup); }
DviFontSizeList * InstallFontSizes (DviWidget dw, const char *x_name, Boolean *scalablep) { char fontNameString[2048]; char **fonts; int i, count; int size; DviFontSizeList *sizes, *new_size; XFontName fontName; unsigned int fontNameAttributes; *scalablep = FALSE; if (!XParseFontName ((XFontNameString)x_name, &fontName, &fontNameAttributes)) return 0; fontNameAttributes &= ~(FontNamePixelSize|FontNamePointSize |FontNameAverageWidth); fontNameAttributes |= FontNameResolutionX; fontNameAttributes |= FontNameResolutionY; fontName.ResolutionX = dw->dvi.display_resolution; fontName.ResolutionY = dw->dvi.display_resolution; XFormatFontName (&fontName, fontNameAttributes, fontNameString); fonts = XListFonts (XtDisplay (dw), fontNameString, 10000000, &count); sizes = 0; for (i = 0; i < count; i++) { size = ConvertFontNameToSize (fonts[i]); if (size == 0) { DisposeFontSizes (dw, sizes); sizes = 0; *scalablep = TRUE; break; } if (size != -1) { new_size = (DviFontSizeList *) XtMalloc (sizeof *new_size); new_size->next = sizes; new_size->size = size; new_size->x_name = savestr (fonts[i]); new_size->doesnt_exist = 0; new_size->font = 0; sizes = new_size; } } XFreeFontNames (fonts); return sizes; }
VOID storedatt(PNE pne) { int i; NEAL(pne) = (struct ad *)rmalloc((1+ADN(al))*ADSZ); memcpy((UNIV)NEAL(pne), (UNIV)al, (1+ADN(al))*ADSZ); for (i = 1; i <= (int)ADN(al); i++) { if (GET(ADFLAGS(al, i), ASPEC)) ds.attdef += ADLEN(al, i); if (NEAL(pne)[i].addef != 0) NEAL(pne)[i].addef = savestr(NEAL(pne)[i].addef); } ds.attcnt += AN(al); /* Number of attributes defined. */ #if 0 /* I can't see any reason to increase AVGRPCNT here. */ ds.attgcnt += ADN(al) - AN(al); /* Number of att grp members. */ #endif }
/* * Deal with arpa net addresses. The way this is done is strange. * name contains an "@" or "%". Look up the machine after it in * the hash table. If it isn't found, return name unmolested. * If ???, return name unmolested. * Otherwise, delete the "@" or "%" and the machine after it from * name, and return the new string. */ static char * arpafix(char name[], char from[]) { register char *cp; register int arpamach; char newname[BUFSIZ]; if (debug) { fprintf(stderr, "arpafix(%s, %s)\n", name, from); } cp = strrchr(name, '@'); if (cp == NOSTR) cp = strrchr(name, '%'); if (cp == NOSTR) { fprintf(stderr, gettext("Something's amiss -- no @ or %% in arpafix\n")); return(name); } cp++; arpamach = netlook(cp, '@'); if (debug) fprintf(stderr, "cp '%s', arpamach %o, nettypes arpamach %o LOCAL %o\n", cp, arpamach, nettype(arpamach), nettype(LOCAL)); if (arpamach == 0) { if (debug) fprintf(stderr, "machine %s unknown, uses: %s\n", cp, name); return(name); } if (((nettype(arpamach) & nettype(LOCAL)) & ~AN) == 0) { if (debug) fprintf(stderr, "machine %s known but remote, uses: %s\n", cp, name); return(name); } nstrcpy(newname, sizeof (newname), name); cp = strrchr(newname, '@'); if (cp == NOSTR) cp = strrchr(newname, '%'); *cp = 0; if (debug) fprintf(stderr, "local address, return '%s'\n", newname); return(savestr(newname)); }
int use_selected() { register SUBJECT *sp; register ARTICLE *ap; bool want_read; char *cmdstr; int len, ret = 1; int subj_mask = (sel_mode == SM_THREAD? (SF_THREAD|SF_VISIT) : SF_VISIT); if (!finish_command(TRUE)) /* get rest of command */ return 0; if (!buf[1]) return -1; cmdstr = savestr(buf+1); want_read = (sel_rereading || *cmdstr =='m'); perform_cnt = 0; page_line = 1; len = strlen(cmdstr); /* A few commands can just loop through the subjects. */ if ((len == 1 && (*cmdstr == 't' || *cmdstr == 'J')) || (len == 2 && (((*cmdstr == '+' || *cmdstr == '-') && cmdstr[0] == cmdstr[1]) || *cmdstr == 'T'))) { for (sp = first_subject; sp; sp = sp->next) { if ((sp->flags & subj_mask) == subj_mask) { artp = first_art(sp); if (artp) { art = article_num(artp); if (perform(cmdstr, FALSE)) { fputs("\nInterrupted\n", stdout) FLUSH; goto break_out; } } #ifdef VERBOSE IF(verbose) if (mode != 't' && *cmdstr != 't' && *cmdstr != 'T') putchar('\n') FLUSH; #endif } } } else if (strEQ(cmdstr, "E")) {
static DviFontSizeList * LookupFontSizeBySize (DviWidget dw, DviFontList *f, int size) { DviFontSizeList *fs, *best = 0, *smallest = 0; int bestsize = 0; XFontName fontName; unsigned int fontNameAttributes; char fontNameString[2048]; int decipointsize; if (f->scalable) { decipointsize = (10*size)/dw->dvi.sizescale; for (best = f->sizes; best; best = best->next) if (best->size == decipointsize) return best; best = (DviFontSizeList *) XtMalloc(sizeof *best); best->next = f->sizes; best->size = decipointsize; f->sizes = best; XParseFontName (f->x_name, &fontName, &fontNameAttributes); fontNameAttributes &= ~(FontNamePixelSize|FontNameAverageWidth); fontNameAttributes |= FontNameResolutionX; fontNameAttributes |= FontNameResolutionY; fontNameAttributes |= FontNamePointSize; fontName.ResolutionX = dw->dvi.display_resolution; fontName.ResolutionY = dw->dvi.display_resolution; fontName.PointSize = decipointsize; XFormatFontName (&fontName, fontNameAttributes, fontNameString); best->x_name = savestr (fontNameString); best->doesnt_exist = 0; best->font = 0; return best; } for (fs = f->sizes; fs; fs=fs->next) { if (dw->dvi.sizescale*fs->size <= 10*size && fs->size >= bestsize) { best = fs; bestsize = fs->size; } if (smallest == 0 || fs->size < smallest->size) smallest = fs; } return best ? best : smallest; }
/* * get_arch_name_from_types() returns the name of the architecture for the * specified cputype and cpusubtype if known. If unknown it returns a pointer * to the an allocated string "cputype X cpusubtype Y" where X and Y are decimal * values. */ __private_extern__ const char * get_arch_name_from_types( cpu_type_t cputype, cpu_subtype_t cpusubtype) { unsigned long i; char *p; for(i = 0; arch_flags[i].name != NULL; i++){ if(arch_flags[i].cputype == cputype && arch_flags[i].cpusubtype == cpusubtype) return(arch_flags[i].name); } p = savestr("cputype 1234567890 cpusubtype 1234567890"); if(p != NULL) sprintf(p, "cputype %u cpusubtype %u", cputype, cpusubtype); return(p); }
/* * Choose the name of the file to be patched based the "best" one * available. */ static char * best_name(const struct file_name *names, bool assume_exists) { char *best; best = compare_names(names, assume_exists, 1); if (best == NULL) { best = compare_names(names, assume_exists, 2); /* * Still no match? Check to see if the diff could be creating * a new file. */ if (best == NULL && ok_to_create_file && names[NEW_FILE].path != NULL) best = names[NEW_FILE].path; } return best ? savestr(best) : NULL; }
void setparam(char **argv) { char **newparam; char **ap; int nparam; for (nparam = 0 ; argv[nparam] ; nparam++); ap = newparam = ckmalloc((nparam + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = nparam; shellparam.p = newparam; shellparam.optnext = NULL; }
static void setparam(int argc, char **argv) { char **newparam; char **ap; ap = newparam = ckmalloc((argc + 1) * sizeof *ap); while (*argv) { *ap++ = savestr(*argv++); } *ap = NULL; freeparam(&shellparam); shellparam.malloc = 1; shellparam.nparam = argc; shellparam.p = newparam; shellparam.optp = NULL; shellparam.reset = 1; shellparam.optnext = NULL; }
/* * $ substitute one word, for i/o redirection */ tchar * Dfix1(tchar *cp) { tchar *Dv[2]; #ifdef TRACE tprintf("TRACE- Dfix1()\n"); #endif if (noexec) return (0); Dv[0] = cp; Dv[1] = NOSTR; Dfix2(Dv); if (gargc != 1) { setname(cp); bferr("Ambiguous"); } cp = savestr(gargv[0]); blkfree(gargv), gargv = 0; return (cp); }
void readlast() { if ((tmpfp = fopen(lastfile,"r")) != NULL) { if (fgets(buf,sizeof buf,tmpfp) != NULL) { long old_last = lasttime; buf[strlen(buf)-1] = '\0'; if (*buf) { safefree0(lastngname); lastngname = savestr(buf); } fscanf(tmpfp,"%ld %ld %ld %ld",&lasttime,&lastactsiz, &lastnewtime,&lastextranum); if (!lastnewtime) lastnewtime = starttime; if (old_last > lasttime) lasttime = old_last; } fclose(tmpfp); } }
/* Add a ethernet code to the database */ int ec_add(register u_int32_t o, register char *text) { if (ec_last >= ec_len) { if (list == NULL) { ec_len = 512; list = malloc(ec_len * sizeof(*list)); } else { ec_len *= 2; list = realloc(list, ec_len * sizeof(*list)); } if (list == NULL) { syslog(LOG_ERR, "ec_add(): malloc: %m"); exit(1); } } list[ec_last].o = o; list[ec_last].text = savestr(text); ++ec_last; return (1); }
/* * Choose the name of the file to be patched based on POSIX rules. * NOTE: the POSIX rules are amazingly stupid and we only follow them * if the user specified --posix or set POSIXLY_CORRECT. */ static char * posix_name(const struct file_name *names, bool assume_exists) { char *path = NULL; int i; /* * POSIX states that the filename will be chosen from one * of the old, new and index names (in that order) if * the file exists relative to CWD after -p stripping. */ for (i = 0; i < MAX_FILE; i++) { if (names[i].path != NULL && names[i].exists) { path = names[i].path; break; } } if (path == NULL && !assume_exists) { /* * No files found, look for something we can checkout from * RCS/SCCS dirs. Same order as above. */ for (i = 0; i < MAX_FILE; i++) { if (names[i].path != NULL && (path = checked_in(names[i].path)) != NULL) break; } /* * Still no match? Check to see if the diff could be creating * a new file. */ if (path == NULL && ok_to_create_file && names[NEW_FILE].path != NULL) path = names[NEW_FILE].path; } return path ? savestr(path) : NULL; }
void varset( /* set a variable's value */ char *vname, int assign, double val ) { char *qname; EPNODE *ep1, *ep2; /* get qualified name */ qname = qualname(vname, 0); /* check for quick set */ if ((ep1 = dlookup(qname)) != NULL && ep1->v.kid->type == SYM && (ep1->type == ':') <= (assign == ':')) { ep2 = ep1->v.kid->sibling; if (ep2->type == NUM) { ep2->v.num = val; ep1->type = assign; return; } } /* hand build definition */ ep1 = newnode(); ep1->type = assign; ep2 = newnode(); ep2->type = SYM; ep2->v.name = savestr(vname); addekid(ep1, ep2); ep2 = newnode(); ep2->type = NUM; ep2->v.num = val; addekid(ep1, ep2); if (assign == ':') dremove(qname); else dclear(qname); dpush(qname, ep1); }
static void _make_zombie(QSP_ARG_DECL Data_Obj *dp) { static int n_zombie=1; char zname[LLEN]; /* this function removes it from the hash table and * active item list, doesn't add the structure to the * item free list. This is why we release the node * and later free the object... * * I think the idea here is that there might be a dangling reference * to an image - for instance, if we display an image, then delete it, * and then later want to refresh the window... */ zombie_item(dobj_itp,(Item *)dp); sprintf(zname,"Z.%s.%d",OBJ_NAME(dp),n_zombie++); fprintf(stderr,"make_zombie, changing object %s to %s\n",OBJ_NAME(dp),zname); rls_str( (char *) OBJ_NAME(dp) ); /* unsave old name, make_zombie */ SET_OBJ_NAME(dp,savestr(zname)); SET_OBJ_FLAG_BITS(dp,DT_ZOMBIE); } // make_zombie
VARDEF * varinsert( /* get a link to a variable */ char *name ) { VARDEF *vp; int hv; if ((vp = varlookup(name)) != NULL) { vp->nlinks++; return(vp); } vp = (VARDEF *)emalloc(sizeof(VARDEF)); vp->lib = liblookup(name); if (vp->lib == NULL) /* if name not in library */ name = qualname(name, 0); /* use fully qualified version */ hv = hash(name); vp->name = savestr(name); vp->nlinks = 1; vp->def = NULL; vp->next = hashtbl[hv]; hashtbl[hv] = vp; return(vp); }
int markall(char buf[], int f) { char **np; int i; struct message *mp; char *namelist[NMLSIZE], *bufp; int tok, beg, mc, star, other, valdot, colmod, colresult; valdot = dot - &message[0] + 1; colmod = 0; for (i = 1; i <= msgCount; i++) unmark(i); bufp = buf; mc = 0; np = &namelist[0]; scaninit(); tok = scan(&bufp); star = 0; other = 0; beg = 0; while (tok != TEOL) { switch (tok) { case TNUMBER: number: if (star) { printf("No numbers mixed with *\n"); return (-1); } mc++; other++; if (beg != 0) { if (check(lexnumber, f)) return (-1); for (i = beg; i <= lexnumber; i++) if (f == MDELETED || (message[i - 1].m_flag & MDELETED) == 0) mark(i); beg = 0; break; } beg = lexnumber; if (check(beg, f)) return (-1); tok = scan(&bufp); regret(tok); if (tok != TDASH) { mark(beg); beg = 0; } break; case TPLUS: if (beg != 0) { printf("Non-numeric second argument\n"); return (-1); } i = valdot; do { i++; if (i > msgCount) { printf("Referencing beyond EOF\n"); return (-1); } } while ((message[i - 1].m_flag & MDELETED) != f); mark(i); break; case TDASH: if (beg == 0) { i = valdot; do { i--; if (i <= 0) { printf("Referencing before 1\n"); return (-1); } } while ((message[i - 1].m_flag & MDELETED) != f); mark(i); } break; case TSTRING: if (beg != 0) { printf("Non-numeric second argument\n"); return (-1); } other++; if (lexstring[0] == ':') { colresult = evalcol(lexstring[1]); if (colresult == 0) { printf("Unknown colon modifier \"%s\"\n", lexstring); return (-1); } colmod |= colresult; } else *np++ = savestr(lexstring); break; case TDOLLAR: case TUP: case TDOT: lexnumber = metamess(lexstring[0], f); if (lexnumber == -1) return (-1); goto number; case TSTAR: if (other) { printf("Can't mix \"*\" with anything\n"); return (-1); } star++; break; case TERROR: return (-1); } tok = scan(&bufp); } lastcolmod = colmod; *np = NULL; mc = 0; if (star) { for (i = 0; i < msgCount; i++) if ((message[i].m_flag & MDELETED) == f) { mark(i+1); mc++; } if (mc == 0) { printf("No applicable messages.\n"); return (-1); } return (0); } /* * If no numbers were given, mark all of the messages, * so that we can unmark any whose sender was not selected * if any user names were given. */ if ((np > namelist || colmod != 0) && mc == 0) for (i = 1; i <= msgCount; i++) if ((message[i-1].m_flag & MDELETED) == f) mark(i); /* * If any names were given, go through and eliminate any * messages whose senders were not requested. */ if (np > namelist) { for (i = 1; i <= msgCount; i++) { for (mc = 0, np = &namelist[0]; *np != NULL; np++) if (**np == '/') { if (matchfield(*np, i)) { mc++; break; } } else { if (matchsender(*np, i)) { mc++; break; } } if (mc == 0) unmark(i); } /* * Make sure we got some decent messages. */ mc = 0; for (i = 1; i <= msgCount; i++) if (message[i-1].m_flag & MMARK) { mc++; break; } if (mc == 0) { printf("No applicable messages from {%s", namelist[0]); for (np = &namelist[1]; *np != NULL; np++) printf(", %s", *np); printf("}\n"); return (-1); } } /* * If any colon modifiers were given, go through and * unmark any messages which do not satisfy the modifiers. */ if (colmod != 0) { for (i = 1; i <= msgCount; i++) { struct coltab *colp; mp = &message[i - 1]; for (colp = &coltab[0]; colp->co_char != '\0'; colp++) if (colp->co_bit & colmod) if ((mp->m_flag & colp->co_mask) != colp->co_equal) unmark(i); } for (mp = &message[0]; mp < &message[msgCount]; mp++) if (mp->m_flag & MMARK) break; if (mp >= &message[msgCount]) { struct coltab *colp; printf("No messages satisfy"); for (colp = &coltab[0]; colp->co_char != '\0'; colp++) if (colp->co_bit & colmod) printf(" :%c", colp->co_char); printf("\n"); return (-1); } } return (0); }
/* * Scan out the list of string arguments, shell style * for a RAWLIST. */ int getrawlist(char line[], char **argv, int argc) { char c, *cp, *cp2, quotec; int argn; char *linebuf; size_t linebufsize = BUFSIZ; if ((linebuf = malloc(linebufsize)) == NULL) err(1, "Out of memory"); argn = 0; cp = line; for (;;) { for (; *cp == ' ' || *cp == '\t'; cp++) ; if (*cp == '\0') break; if (argn >= argc - 1) { printf( "Too many elements in the list; excess discarded.\n"); break; } cp2 = linebuf; quotec = '\0'; while ((c = *cp) != '\0') { /* Allocate more space if necessary */ if (cp2 - linebuf == linebufsize - 1) { linebufsize += BUFSIZ; if ((linebuf = realloc(linebuf, linebufsize)) == NULL) err(1, "Out of memory"); cp2 = linebuf + linebufsize - BUFSIZ - 1; } cp++; if (quotec != '\0') { if (c == quotec) quotec = '\0'; else if (c == '\\') switch (c = *cp++) { case '\0': *cp2++ = '\\'; cp--; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': c -= '0'; if (*cp >= '0' && *cp <= '7') c = c * 8 + *cp++ - '0'; if (*cp >= '0' && *cp <= '7') c = c * 8 + *cp++ - '0'; *cp2++ = c; break; case 'b': *cp2++ = '\b'; break; case 'f': *cp2++ = '\f'; break; case 'n': *cp2++ = '\n'; break; case 'r': *cp2++ = '\r'; break; case 't': *cp2++ = '\t'; break; case 'v': *cp2++ = '\v'; break; default: *cp2++ = c; } else if (c == '^') { c = *cp++; if (c == '?') *cp2++ = '\177'; /* null doesn't show up anyway */ else if ((c >= 'A' && c <= '_') || (c >= 'a' && c <= 'z')) *cp2++ = c & 037; else { *cp2++ = '^'; cp--; } } else *cp2++ = c; } else if (c == '"' || c == '\'') quotec = c; else if (c == ' ' || c == '\t') break; else *cp2++ = c; } *cp2 = '\0'; argv[argn++] = savestr(linebuf); } argv[argn] = NULL; (void)free(linebuf); return (argn); }
FILE * collect(struct header *hp, int printheaders) { FILE *fbuf; int lc, cc, escape, eofcount, fd, c, t; char linebuf[LINESIZE], tempname[PATHSIZE], *cp, getsub; sigset_t nset; int longline, lastlong, rc; /* So we don't make 2 or more lines out of a long input line. */ collf = NULL; /* * Start catching signals from here, but we're still die on interrupts * until we're in the main loop. */ (void)sigemptyset(&nset); (void)sigaddset(&nset, SIGINT); (void)sigaddset(&nset, SIGHUP); (void)sigprocmask(SIG_BLOCK, &nset, NULL); if ((saveint = signal(SIGINT, SIG_IGN)) != SIG_IGN) (void)signal(SIGINT, collint); if ((savehup = signal(SIGHUP, SIG_IGN)) != SIG_IGN) (void)signal(SIGHUP, collhup); savetstp = signal(SIGTSTP, collstop); savettou = signal(SIGTTOU, collstop); savettin = signal(SIGTTIN, collstop); if (setjmp(collabort) || setjmp(colljmp)) { (void)rm(tempname); goto err; } (void)sigprocmask(SIG_UNBLOCK, &nset, NULL); noreset++; (void)snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir); if ((fd = mkstemp(tempname)) == -1 || (collf = Fdopen(fd, "w+")) == NULL) { warn("%s", tempname); goto err; } (void)rm(tempname); /* * If we are going to prompt for a subject, * refrain from printing a newline after * the headers (since some people mind). */ t = GTO|GSUBJECT|GCC|GNL; getsub = 0; if (hp->h_subject == NULL && value("interactive") != NULL && (value("ask") != NULL || value("asksub") != NULL)) t &= ~GNL, getsub++; if (printheaders) { puthead(hp, stdout, t); (void)fflush(stdout); } if ((cp = value("escape")) != NULL) escape = *cp; else escape = ESCAPE; eofcount = 0; hadintr = 0; lastlong = 0; longline = 0; if (!setjmp(colljmp)) { if (getsub) grabh(hp, GSUBJECT); } else { /* * Come here for printing the after-signal message. * Duplicate messages won't be printed because * the write is aborted if we get a SIGTTOU. */ cont: if (hadintr) { (void)fflush(stdout); fprintf(stderr, "\n(Interrupt -- one more to kill letter)\n"); } else { printf("(continue)\n"); (void)fflush(stdout); } } for (;;) { colljmp_p = 1; c = readline(stdin, linebuf, LINESIZE); colljmp_p = 0; if (c < 0) { if (value("interactive") != NULL && value("ignoreeof") != NULL && ++eofcount < 25) { printf("Use \".\" to terminate letter\n"); continue; } break; } lastlong = longline; longline = c == LINESIZE - 1; eofcount = 0; hadintr = 0; if (linebuf[0] == '.' && linebuf[1] == '\0' && value("interactive") != NULL && !lastlong && (value("dot") != NULL || value("ignoreeof") != NULL)) break; if (linebuf[0] != escape || value("interactive") == NULL || lastlong) { if (putline(collf, linebuf, !longline) < 0) goto err; continue; } c = linebuf[1]; switch (c) { default: /* * On double escape, just send the single one. * Otherwise, it's an error. */ if (c == escape) { if (putline(collf, &linebuf[1], !longline) < 0) goto err; else break; } printf("Unknown tilde escape.\n"); break; case 'C': /* * Dump core. */ core(); break; case '!': /* * Shell escape, send the balance of the * line to sh -c. */ shell(&linebuf[2]); break; case ':': case '_': /* * Escape to command mode, but be nice! */ execute(&linebuf[2], 1); goto cont; case '.': /* * Simulate end of file on input. */ goto out; case 'q': /* * Force a quit of sending mail. * Act like an interrupt happened. */ hadintr++; collint(SIGINT); exit(1); case 'x': /* * Exit, do not save in dead.letter. */ goto err; case 'h': /* * Grab a bunch of headers. */ grabh(hp, GTO|GSUBJECT|GCC|GBCC); goto cont; case 't': /* * Add to the To list. */ hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO)); break; case 's': /* * Set the Subject line. */ cp = &linebuf[2]; while (isspace((unsigned char)*cp)) cp++; hp->h_subject = savestr(cp); break; case 'R': /* * Set the Reply-To line. */ cp = &linebuf[2]; while (isspace((unsigned char)*cp)) cp++; hp->h_replyto = savestr(cp); break; case 'c': /* * Add to the CC list. */ hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC)); break; case 'b': /* * Add to the BCC list. */ hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); break; case 'i': case 'A': case 'a': /* * Insert named variable in message. */ switch(c) { case 'i': cp = &linebuf[2]; while(isspace((unsigned char)*cp)) cp++; break; case 'a': cp = "sign"; break; case 'A': cp = "Sign"; break; default: goto err; } if(*cp != '\0' && (cp = value(cp)) != NULL) { printf("%s\n", cp); if(putline(collf, cp, 1) < 0) goto err; } break; case 'd': /* * Read in the dead letter file. */ if (strlcpy(linebuf + 2, getdeadletter(), sizeof(linebuf) - 2) >= sizeof(linebuf) - 2) { printf("Line buffer overflow\n"); break; } /* FALLTHROUGH */ case 'r': case '<': /* * Invoke a file: * Search for the file name, * then open it and copy the contents to collf. */ cp = &linebuf[2]; while (isspace((unsigned char)*cp)) cp++; if (*cp == '\0') { printf("Interpolate what file?\n"); break; } cp = expand(cp); if (cp == NULL) break; if (*cp == '!') { /* * Insert stdout of command. */ char *sh; int nullfd, tempfd, rc; char tempname2[PATHSIZE]; if ((nullfd = open(_PATH_DEVNULL, O_RDONLY, 0)) == -1) { warn(_PATH_DEVNULL); break; } (void)snprintf(tempname2, sizeof(tempname2), "%s/mail.ReXXXXXXXXXX", tmpdir); if ((tempfd = mkstemp(tempname2)) == -1 || (fbuf = Fdopen(tempfd, "w+")) == NULL) { warn("%s", tempname2); break; } (void)unlink(tempname2); if ((sh = value("SHELL")) == NULL) sh = _PATH_CSHELL; rc = run_command(sh, 0, nullfd, fileno(fbuf), "-c", cp+1, NULL); close(nullfd); if (rc < 0) { (void)Fclose(fbuf); break; } if (fsize(fbuf) == 0) { fprintf(stderr, "No bytes from command \"%s\"\n", cp+1); (void)Fclose(fbuf); break; } rewind(fbuf); } else if (isdir(cp)) { printf("%s: Directory\n", cp); break; } else if ((fbuf = Fopen(cp, "r")) == NULL) { warn("%s", cp); break; } printf("\"%s\" ", cp); (void)fflush(stdout); lc = 0; cc = 0; while ((rc = readline(fbuf, linebuf, LINESIZE)) >= 0) { if (rc != LINESIZE - 1) lc++; if ((t = putline(collf, linebuf, rc != LINESIZE - 1)) < 0) { (void)Fclose(fbuf); goto err; } cc += t; } (void)Fclose(fbuf); printf("%d/%d\n", lc, cc); break; case 'w': /* * Write the message on a file. */ cp = &linebuf[2]; while (*cp == ' ' || *cp == '\t') cp++; if (*cp == '\0') { fprintf(stderr, "Write what file!?\n"); break; } if ((cp = expand(cp)) == NULL) break; rewind(collf); exwrite(cp, collf, 1); break; case 'm': case 'M': case 'f': case 'F': /* * Interpolate the named messages, if we * are in receiving mail mode. Does the * standard list processing garbage. * If ~f is given, we don't shift over. */ if (forward(linebuf + 2, collf, tempname, c) < 0) goto err; goto cont; case '?': if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) { warn("%s", _PATH_TILDE); break; } while ((t = getc(fbuf)) != EOF) (void)putchar(t); (void)Fclose(fbuf); break; case 'p': /* * Print out the current state of the * message without altering anything. */ rewind(collf); printf("-------\nMessage contains:\n"); puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); while ((t = getc(collf)) != EOF) (void)putchar(t); goto cont; case '|': /* * Pipe message through command. * Collect output as new message. */ rewind(collf); mespipe(collf, &linebuf[2]); goto cont; case 'v': case 'e': /* * Edit the current message. * 'e' means to use EDITOR * 'v' means to use VISUAL */ rewind(collf); mesedit(collf, c); goto cont; } } goto out; err: if (collf != NULL) { (void)Fclose(collf); collf = NULL; } out: if (collf != NULL) rewind(collf); noreset--; (void)sigprocmask(SIG_BLOCK, &nset, NULL); (void)signal(SIGINT, saveint); (void)signal(SIGHUP, savehup); (void)signal(SIGTSTP, savetstp); (void)signal(SIGTTOU, savettou); (void)signal(SIGTTIN, savettin); (void)sigprocmask(SIG_UNBLOCK, &nset, NULL); return (collf); }
int trapcmd(int argc, char **argv) { char *action; char **ap; int signo; if (argc <= 1) { for (signo = 0 ; signo <= NSIG ; signo++) if (trap[signo] != NULL) { out1fmt("trap -- "); print_quoted(trap[signo]); out1fmt(" %s\n", (signo) ? sys_signame[signo] : "EXIT"); } return 0; } ap = argv + 1; action = NULL; if (strcmp(*ap, "--") == 0) if (*++ap == NULL) return 0; if (signame_to_signum(*ap) == -1) { if ((*ap)[0] == '-') { if ((*ap)[1] == '\0') ap++; else if ((*ap)[1] == 'l' && (*ap)[2] == '\0') { printsignals(); return 0; } else error("bad option %s\n", *ap); } else action = *ap++; } while (*ap) { if (is_number(*ap)) signo = number(*ap); else signo = signame_to_signum(*ap); if (signo < 0 || signo > NSIG) error("%s: bad trap", *ap); INTOFF; if (action) action = savestr(action); if (trap[signo]) ckfree(trap[signo]); trap[signo] = action; if (signo != 0) setsignal(signo, 0); INTON; ap++; } return 0; }
/* * Read up a header from standard input. * The source string has the preliminary contents to * be read. * */ char * readtty(char *pr, char *src) { struct sigaction act, saveint; char ch, canonb[BUFSIZ]; char *cp, *cp2; sigset_t oset; int c; fputs(pr, stdout); fflush(stdout); if (src != NULL && strlen(src) > sizeof(canonb) - 2) { puts("too long to edit"); return(src); } #ifndef TIOCSTI if (src != NULL) cp = copy(src, canonb); /* safe, bounds checked above */ else cp = copy("", canonb); fputs(canonb, stdout); fflush(stdout); #else cp = src == NULL ? "" : src; while ((c = (unsigned char)*cp++) != '\0') { if ((c_erase != _POSIX_VDISABLE && c == c_erase) || (c_kill != _POSIX_VDISABLE && c == c_kill)) { ch = '\\'; ioctl(0, TIOCSTI, &ch); } ch = c; ioctl(0, TIOCSTI, &ch); } cp = canonb; *cp = 0; #endif sigemptyset(&act.sa_mask); act.sa_flags = 0; /* Note: will not restart syscalls */ act.sa_handler = ttyint; (void)sigaction(SIGINT, &act, &saveint); act.sa_handler = ttystop; (void)sigaction(SIGTSTP, &act, NULL); (void)sigaction(SIGTTOU, &act, NULL); (void)sigaction(SIGTTIN, &act, NULL); (void)sigprocmask(SIG_UNBLOCK, &intset, &oset); clearerr(stdin); memset(cp, 0, canonb + sizeof(canonb) - cp); for (cp2 = cp; cp2 < canonb + sizeof(canonb) - 1; ) { c = getc(stdin); switch (ttysignal) { case SIGINT: ttysignal = 0; cp2 = NULL; c = EOF; /* FALLTHROUGH */ case 0: break; default: ttysignal = 0; goto redo; } if (c == EOF || c == '\n') break; *cp2++ = c; } act.sa_handler = SIG_DFL; sigemptyset(&act.sa_mask); act.sa_flags = SA_RESTART; (void)sigprocmask(SIG_SETMASK, &oset, NULL); (void)sigaction(SIGTSTP, &act, NULL); (void)sigaction(SIGTTOU, &act, NULL); (void)sigaction(SIGTTIN, &act, NULL); (void)sigaction(SIGINT, &saveint, NULL); if (cp2 == NULL) return(NULL); /* user hit ^C */ *cp2 = '\0'; if (c == EOF && ferror(stdin)) { redo: cp = strlen(canonb) > 0 ? canonb : NULL; clearerr(stdin); /* XXX - make iterative, not recursive */ return(readtty(pr, cp)); } #ifndef TIOCSTI if (cp == NULL || *cp == '\0') return(src); cp2 = cp; if (!ttyset) return(strlen(canonb) > 0 ? savestr(canonb) : NULL); while (*cp != '\0') { c = (unsigned char)*cp++; if (c_erase != _POSIX_VDISABLE && c == c_erase) { if (cp2 == canonb) continue; if (cp2[-1] == '\\') { cp2[-1] = c; continue; } cp2--; continue; } if (c_kill != _POSIX_VDISABLE && c == c_kill) { if (cp2 == canonb) continue; if (cp2[-1] == '\\') { cp2[-1] = c; continue; } cp2 = canonb; continue; } *cp2++ = c; } *cp2 = '\0'; #endif if (equal("", canonb)) return(""); return(savestr(canonb)); }
FILE * collect(struct header *hp, int printheaders, struct message *mp, char *quotefile, int doprefix, int tflag) { FILE *fbuf; struct ignoretab *quoteig; int lc, cc, escape, eofcount; int c, t; char *linebuf = NULL, *cp, *quote = NULL; size_t linesize; char *tempMail = NULL; int getfields; sigset_t oset, nset; long count; enum sendaction action; sighandler_type savedtop; const char tildehelp[] = "-------------------- ~ ESCAPES ----------------------------\n\ ~~ Quote a single tilde\n\ ~@ [file ...] Edit attachment list\n\ ~b users Add users to \"blind\" cc list\n\ ~c users Add users to cc list\n\ ~d Read in dead.letter\n\ ~e Edit the message buffer\n\ ~f messages Read in messages without indenting lines\n\ ~F messages Same as ~f, but keep all header lines\n\ ~h Prompt for to list, subject, cc, and \"blind\" cc list\n\ ~r file Read a file into the message buffer\n\ ~p Print the message buffer\n\ ~q Abort message composition and save text to dead.letter\n\ ~m messages Read in messages with each line indented\n\ ~M messages Same as ~m, but keep all header lines\n\ ~s subject Set subject\n\ ~t users Add users to to list\n\ ~v Invoke display editor on message\n\ ~w file Write message onto file\n\ ~x Abort message composition and discard text written so far\n\ ~!command Invoke the shell\n\ ~:command Execute a regular command\n\ -----------------------------------------------------------\n"; (void) &escape; (void) &eofcount; (void) &getfields; (void) &tempMail; (void) &tflag; (void) "e; collf = NULL; /* * Start catching signals from here, but we're still die on interrupts * until we're in the main loop. */ sigemptyset(&nset); sigaddset(&nset, SIGINT); sigaddset(&nset, SIGHUP); sigprocmask(SIG_BLOCK, &nset, &oset); handlerpush(collint); if ((saveint = safe_signal(SIGINT, SIG_IGN)) != SIG_IGN) safe_signal(SIGINT, collint); if ((savehup = safe_signal(SIGHUP, SIG_IGN)) != SIG_IGN) safe_signal(SIGHUP, collhup); savetstp = safe_signal(SIGTSTP, collstop); savettou = safe_signal(SIGTTOU, collstop); savettin = safe_signal(SIGTTIN, collstop); if (sigsetjmp(collabort, 1)) { if (tempMail != NULL) { rm(tempMail); Ftfree(&tempMail); } goto err; } if (sigsetjmp(colljmp, 1)) { if (tempMail != NULL) { rm(tempMail); Ftfree(&tempMail); } goto err; } sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); noreset++; if ((collf = Ftemp(&tempMail, "Rs", "w+", 0600, 1)) == NULL) { perror(catgets(catd, CATSET, 51, "temporary mail file")); goto err; } unlink(tempMail); Ftfree(&tempMail); if ((cp = value("MAILX_HEAD")) != NULL) { if (is_a_tty[0]) putesc(cp, stdout); putesc(cp, collf); } /* * If we are going to prompt for a subject, * refrain from printing a newline after * the headers (since some people mind). */ getfields = 0; if (!tflag) { t = GTO|GSUBJECT|GCC|GNL; if (value("fullnames")) t |= GCOMMA; if (hp->h_subject == NULL && value("interactive") != NULL && (value("ask") != NULL || value("asksub") != NULL)) t &= ~GNL, getfields |= GSUBJECT; if (hp->h_to == NULL && value("interactive") != NULL) t &= ~GNL, getfields |= GTO; if (value("bsdcompat") == NULL && value("askatend") == NULL && value("interactive")) { if (hp->h_bcc == NULL && value("askbcc")) t &= ~GNL, getfields |= GBCC; if (hp->h_cc == NULL && value("askcc")) t &= ~GNL, getfields |= GCC; } if (printheaders) { puthead(hp, stdout, t, SEND_TODISP, CONV_NONE, NULL, NULL); fflush(stdout); } } /* * Quote an original message */ if (mp != NULL && (doprefix || (quote = value("quote")) != NULL)) { quoteig = allignore; action = SEND_QUOTE; if (doprefix) { quoteig = fwdignore; if ((cp = value("fwdheading")) == NULL) cp = "-------- Original Message --------"; if (*cp) { fprintf(collf, "%s\n", cp); fprintf(stdout, "%s\n", cp); } } else if (strcmp(quote, "noheading") == 0) { /*EMPTY*/; } else if (strcmp(quote, "headers") == 0) { quoteig = ignore; } else if (strcmp(quote, "allheaders") == 0) { quoteig = NULL; action = SEND_QUOTE_ALL; } else { cp = hfield("from", mp); if (cp != NULL) { mime_write(cp, strlen(cp), collf, CONV_FROMHDR, TD_NONE, NULL, (size_t) 0, NULL, NULL); mime_write(cp, strlen(cp), stdout, CONV_FROMHDR, TD_NONE, NULL, (size_t) 0, NULL, NULL); fwrite(catgets(catd, CATSET, 52, " wrote:\n\n"), sizeof(char), 9, collf); fwrite(catgets(catd, CATSET, 52, " wrote:\n\n"), sizeof(char), 9, stdout); } } cp = value("indentprefix"); if (cp != NULL && *cp == '\0') cp = "\t"; send(mp, collf, quoteig, doprefix ? NULL : cp, action, NULL); send(mp, stdout, quoteig, doprefix ? NULL : cp, action, NULL); } if ((cp = value("escape")) != NULL) escape = *cp; else escape = ESCAPE; eofcount = 0; hadintr = 0; if (!sigsetjmp(colljmp, 1)) { if (getfields) grabh(hp, getfields, 1); if (quotefile != NULL) { if (include_file(NULL, quotefile, &lc, &cc, 1) != 0) goto err; } } else { /* * Come here for printing the after-signal message. * Duplicate messages won't be printed because * the write is aborted if we get a SIGTTOU. */ cont: if (hadintr) { fflush(stdout); fprintf(stderr, catgets(catd, CATSET, 53, "\n(Interrupt -- one more to kill letter)\n")); } else { printf(catgets(catd, CATSET, 54, "(continue)\n")); fflush(stdout); } } if (value("interactive") == NULL && tildeflag <= 0 && !is_a_tty[0] && !tflag) { /* * No tilde escapes, interrupts not expected. Copy * standard input the simple way. */ linebuf = srealloc(linebuf, linesize = BUFSIZ); while ((count = fread(linebuf, sizeof *linebuf, linesize, stdin)) > 0) { if (fwrite(linebuf, sizeof *linebuf, count, collf) != count) goto err; } goto out; } for (;;) { colljmp_p = 1; count = readline(stdin, &linebuf, &linesize); colljmp_p = 0; if (count < 0) { if (value("interactive") != NULL && value("ignoreeof") != NULL && ++eofcount < 25) { printf(catgets(catd, CATSET, 55, "Use \".\" to terminate letter\n")); continue; } break; } if (tflag && count == 0) { rewind(collf); if (makeheader(collf, hp) != OKAY) goto err; rewind(collf); tflag = 0; continue; } eofcount = 0; hadintr = 0; if (linebuf[0] == '.' && linebuf[1] == '\0' && value("interactive") != NULL && (value("dot") != NULL || value("ignoreeof") != NULL)) break; if (linebuf[0] != escape || (value("interactive") == NULL && tildeflag == 0 || tildeflag < 0)) { if (putline(collf, linebuf, count) < 0) goto err; continue; } c = linebuf[1]; switch (c) { default: /* * On double escape, just send the single one. * Otherwise, it's an error. */ if (c == escape) { if (putline(collf, &linebuf[1], count - 1) < 0) goto err; else break; } printf(catgets(catd, CATSET, 56, "Unknown tilde escape.\n")); break; #ifdef DEBUG_COMMANDS case 'C': /* * Dump core. */ core(NULL); break; #endif /* DEBUG_COMMANDS */ case '!': /* * Shell escape, send the balance of the * line to sh -c. */ shell(&linebuf[2]); break; case ':': case '_': /* * Escape to command mode, but be nice! */ inhook = 0; execute(&linebuf[2], 1, count - 2); goto cont; case '.': /* * Simulate end of file on input. */ goto out; case 'x': /* * Same as 'q', but no dead.letter saving. */ hadintr++; collint(0); exit(1); /*NOTREACHED*/ case 'q': /* * Force a quit of sending mail. * Act like an interrupt happened. */ hadintr++; collint(SIGINT); exit(1); /*NOTREACHED*/ case 'h': /* * Grab a bunch of headers. */ do grabh(hp, GTO|GSUBJECT|GCC|GBCC, value("bsdcompat") != NULL && value("bsdorder") != NULL); while (hp->h_to == NULL); goto cont; case 'H': /* * Grab extra headers. */ do grabh(hp, GEXTRA, 0); while (check_from_and_sender(hp->h_from, hp->h_sender)); goto cont; case 't': /* * Add to the To list. */ while ((hp->h_to = checkaddrs(cat(hp->h_to, sextract(&linebuf[2], GTO|GFULL)))) == NULL); break; case 's': /* * Set the Subject list. */ cp = &linebuf[2]; while (whitechar(*cp & 0377)) cp++; hp->h_subject = savestr(cp); break; case '@': /* * Edit the attachment list. */ if (linebuf[2] != '\0') hp->h_attach = append_attachments(hp->h_attach, &linebuf[2]); else hp->h_attach = edit_attachments(hp->h_attach); break; case 'c': /* * Add to the CC list. */ hp->h_cc = checkaddrs(cat(hp->h_cc, sextract(&linebuf[2], GCC|GFULL))); break; case 'b': /* * Add stuff to blind carbon copies list. */ hp->h_bcc = checkaddrs(cat(hp->h_bcc, sextract(&linebuf[2], GBCC|GFULL))); break; case 'd': strncpy(linebuf + 2, getdeadletter(), linesize - 2); linebuf[linesize-1]='\0'; /*FALLTHRU*/ case 'r': case '<': /* * Invoke a file: * Search for the file name, * then open it and copy the contents to collf. */ cp = &linebuf[2]; while (whitechar(*cp & 0377)) cp++; if (*cp == '\0') { printf(catgets(catd, CATSET, 57, "Interpolate what file?\n")); break; } if (*cp == '!') { insertcommand(collf, cp + 1); break; } cp = expand(cp); if (cp == NULL) break; if (is_dir(cp)) { printf(catgets(catd, CATSET, 58, "%s: Directory\n"), cp); break; } if ((fbuf = Fopen(cp, "r")) == NULL) { perror(cp); break; } printf(catgets(catd, CATSET, 59, "\"%s\" "), cp); fflush(stdout); if (include_file(fbuf, cp, &lc, &cc, 0) != 0) goto err; printf(catgets(catd, CATSET, 60, "%d/%d\n"), lc, cc); break; case 'i': /* * Insert an environment variable into the file. */ cp = &linebuf[2]; while (whitechar(*cp & 0377)) cp++; if ((cp = value(cp)) == NULL || *cp == '\0') break; if (is_a_tty[0]) putesc(cp, stdout); putesc(cp, collf); break; case 'a': case 'A': /* * Insert the contents of a signature variable. */ if ((cp = value(c == 'a' ? "sign" : "Sign")) != NULL && *cp != '\0') { if (is_a_tty[0]) putesc(cp, stdout); putesc(cp, collf); } break; case 'w': /* * Write the message on a file. */ cp = &linebuf[2]; while (blankchar(*cp & 0377)) cp++; if (*cp == '\0') { fprintf(stderr, catgets(catd, CATSET, 61, "Write what file!?\n")); break; } if ((cp = expand(cp)) == NULL) break; rewind(collf); exwrite(cp, collf, 1); break; case 'm': case 'M': case 'f': case 'F': /* * Interpolate the named messages, if we * are in receiving mail mode. Does the * standard list processing garbage. * If ~f is given, we don't shift over. */ if (forward(linebuf + 2, collf, c) < 0) goto err; goto cont; case '?': fputs(tildehelp, stdout); break; case 'p': /* * Print out the current state of the * message without altering anything. */ print_collf(collf, hp); goto cont; case '|': /* * Pipe message through command. * Collect output as new message. */ rewind(collf); mespipe(&linebuf[2]); goto cont; case 'v': case 'e': /* * Edit the current message. * 'e' means to use EDITOR * 'v' means to use VISUAL */ rewind(collf); mesedit(c, value("editheaders") ? hp : NULL); goto cont; } } goto out; err: if (collf != NULL) { Fclose(collf); collf = NULL; } out: if (collf != NULL) { if ((cp = value("MAILX_TAIL")) != NULL) { if (is_a_tty[0]) putesc(cp, stdout); fflush(collf); putesc(cp, collf); } rewind(collf); } handlerpop(); noreset--; sigemptyset(&nset); sigaddset(&nset, SIGINT); sigaddset(&nset, SIGHUP); #ifndef OLDBUG sigprocmask(SIG_BLOCK, &nset, (sigset_t *)NULL); #else sigprocmask(SIG_BLOCK, &nset, &oset); #endif safe_signal(SIGINT, saveint); safe_signal(SIGHUP, savehup); safe_signal(SIGTSTP, savetstp); safe_signal(SIGTTOU, savettou); safe_signal(SIGTTIN, savettin); sigprocmask(SIG_SETMASK, &oset, (sigset_t *)NULL); return collf; }
/* * get_arch_from_host() gets the architecture from the host this is running on * and returns zero if the architecture is not known and zero if the * architecture is known. If the parameters family_arch_flag and * specific_arch_flag are not NULL they get fill in with the family * architecture and specific architecure for the host. If the architecture * is unknown and the parameters are not NULL then all fields are set to zero. */ __private_extern__ int get_arch_from_host( struct arch_flag *family_arch_flag, struct arch_flag *specific_arch_flag) { struct host_basic_info host_basic_info; unsigned int count; kern_return_t r; mach_port_t my_mach_host_self; if(family_arch_flag != NULL) memset(family_arch_flag, '\0', sizeof(struct arch_flag)); if(specific_arch_flag != NULL) memset(specific_arch_flag, '\0', sizeof(struct arch_flag)); count = HOST_BASIC_INFO_COUNT; my_mach_host_self = mach_host_self(); if((r = host_info(my_mach_host_self, HOST_BASIC_INFO, (host_info_t)(&host_basic_info), &count)) != KERN_SUCCESS) { mach_port_deallocate(mach_task_self(), my_mach_host_self); return(0); } mach_port_deallocate(mach_task_self(), my_mach_host_self); if(family_arch_flag != NULL) { family_arch_flag->cputype = host_basic_info.cpu_type; } if(specific_arch_flag != NULL) { specific_arch_flag->cputype = host_basic_info.cpu_type; specific_arch_flag->cpusubtype = host_basic_info.cpu_subtype; } switch(host_basic_info.cpu_type) { case CPU_TYPE_MC680x0: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_MC680x0_ALL: case CPU_SUBTYPE_MC68030_ONLY: if(family_arch_flag != NULL) { family_arch_flag->name = "m68k"; family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL; } if(specific_arch_flag != NULL) { specific_arch_flag->name = "m68030"; /* * There is a "bug" in the kernel for compatiblity that on * an 030 machine host_info() returns cpusubtype * CPU_SUBTYPE_MC680x0_ALL and not CPU_SUBTYPE_MC68030_ONLY. */ specific_arch_flag->cpusubtype = CPU_SUBTYPE_MC68030_ONLY; } return(1); case CPU_SUBTYPE_MC68040: if(family_arch_flag != NULL) { family_arch_flag->name = "m68k"; family_arch_flag->cpusubtype = CPU_SUBTYPE_MC680x0_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "m68040"; return(1); } break; case CPU_TYPE_POWERPC: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_POWERPC_ALL: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc"; return(1); case CPU_SUBTYPE_POWERPC_601: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc601"; return(1); case CPU_SUBTYPE_POWERPC_603: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc603"; return(1); case CPU_SUBTYPE_POWERPC_603e: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc603e"; return(1); case CPU_SUBTYPE_POWERPC_603ev: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc603ev"; return(1); case CPU_SUBTYPE_POWERPC_604: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc604"; return(1); case CPU_SUBTYPE_POWERPC_604e: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc604e"; return(1); case CPU_SUBTYPE_POWERPC_750: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc750"; return(1); case CPU_SUBTYPE_POWERPC_7400: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc7400"; return(1); case CPU_SUBTYPE_POWERPC_7450: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc7450"; return(1); case CPU_SUBTYPE_POWERPC_970: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "ppc970"; return(1); default: if(family_arch_flag != NULL) { family_arch_flag->name = "ppc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_POWERPC_ALL; } if(specific_arch_flag != NULL) { specific_arch_flag->name = savestr("PowerPC cpusubtype 1234567890"); if(specific_arch_flag->name != NULL) sprintf(specific_arch_flag->name, "PowerPC cpusubtype %u", host_basic_info.cpu_subtype); } return(1); } break; case CPU_TYPE_VEO: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_VEO_1: if(family_arch_flag != NULL) { family_arch_flag->name = "veo"; family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "veo1"; return(1); case CPU_SUBTYPE_VEO_2: if(family_arch_flag != NULL) { family_arch_flag->name = "veo"; family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "veo2"; return(1); case CPU_SUBTYPE_VEO_3: if(family_arch_flag != NULL) { family_arch_flag->name = "veo"; family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "veo3"; return(1); case CPU_SUBTYPE_VEO_4: if(family_arch_flag != NULL) { family_arch_flag->name = "veo"; family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "veo4"; return(1); default: if(family_arch_flag != NULL) { family_arch_flag->name = "veo"; family_arch_flag->cpusubtype = CPU_SUBTYPE_VEO_ALL; } if(specific_arch_flag != NULL) { specific_arch_flag->name = savestr("VEO cpusubtype 1234567890"); sprintf(specific_arch_flag->name, "VEO cpusubtype %u", host_basic_info.cpu_subtype); } return(1); } break; case CPU_TYPE_MC88000: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_MC88000_ALL: case CPU_SUBTYPE_MC88110: if(family_arch_flag != NULL) { family_arch_flag->name = "m88k"; family_arch_flag->cpusubtype = CPU_SUBTYPE_MC88000_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "m88k"; return(1); } break; case CPU_TYPE_I386: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_I386_ALL: /* case CPU_SUBTYPE_386: same value as above */ if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "i386"; return(1); case CPU_SUBTYPE_486: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "i486"; return(1); case CPU_SUBTYPE_486SX: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "i486SX"; return(1); case CPU_SUBTYPE_PENT: /* same as CPU_SUBTYPE_586 */ if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "pentium"; return(1); case CPU_SUBTYPE_PENTPRO: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "pentpro"; return(1); case CPU_SUBTYPE_PENTII_M3: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "pentIIm3"; return(1); case CPU_SUBTYPE_PENTII_M5: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "pentIIm5"; return(1); case CPU_SUBTYPE_PENTIUM_4: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "pentium4"; return(1); default: if(family_arch_flag != NULL) { family_arch_flag->name = "i386"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I386_ALL; } if(specific_arch_flag != NULL) { specific_arch_flag->name = savestr("Intel family 12 model 12345678"); if(specific_arch_flag->name != NULL) sprintf(specific_arch_flag->name, "Intel family %u model %u", CPU_SUBTYPE_INTEL_FAMILY(host_basic_info.cpu_subtype), CPU_SUBTYPE_INTEL_MODEL(host_basic_info.cpu_subtype)); } return(1); } break; case CPU_TYPE_I860: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_I860_ALL: case CPU_SUBTYPE_I860_860: if(family_arch_flag != NULL) { family_arch_flag->name = "i860"; family_arch_flag->cpusubtype = CPU_SUBTYPE_I860_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "i860"; return(1); } break; case CPU_TYPE_HPPA: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_HPPA_ALL: if(family_arch_flag != NULL) { family_arch_flag->name = "hppa"; family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "hppa"; return(1); case CPU_SUBTYPE_HPPA_7100LC: if(family_arch_flag != NULL) { family_arch_flag->name = "hppa"; family_arch_flag->cpusubtype = CPU_SUBTYPE_HPPA_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "hppa7100LC"; return(1); } break; case CPU_TYPE_SPARC: switch(host_basic_info.cpu_subtype) { case /*CPU_SUBTYPE_SPARC_ALL*/0: if(family_arch_flag != NULL) { family_arch_flag->name = "sparc"; family_arch_flag->cpusubtype = CPU_SUBTYPE_SPARC_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "sparc"; return(1); } break; case CPU_TYPE_ARM: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_ARM_ALL: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "arm"; return(1); case CPU_SUBTYPE_ARM_V4T: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv4t"; return(1); case CPU_SUBTYPE_ARM_V5TEJ: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv5"; return(1); case CPU_SUBTYPE_ARM_XSCALE: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "xscale"; return(1); case CPU_SUBTYPE_ARM_V6: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv6"; return(1); case CPU_SUBTYPE_ARM_V6M: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv6m"; return(1); case CPU_SUBTYPE_ARM_V7: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7"; return(1); case CPU_SUBTYPE_ARM_V7F: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7f"; return(1); case CPU_SUBTYPE_ARM_V7S: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7s"; return(1); case CPU_SUBTYPE_ARM_V7K: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7k"; return(1); case CPU_SUBTYPE_ARM_V7M: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7m"; return(1); case CPU_SUBTYPE_ARM_V7EM: if(family_arch_flag != NULL) { family_arch_flag->name = "arm"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "armv7em"; return(1); } break; case CPU_TYPE_ARM64: switch(host_basic_info.cpu_subtype) { case CPU_SUBTYPE_ARM64_ALL: if(family_arch_flag != NULL) { family_arch_flag->name = "arm64"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "arm64"; return(1); case CPU_SUBTYPE_ARM64_V8: if(family_arch_flag != NULL) { family_arch_flag->name = "arm64"; family_arch_flag->cpusubtype = CPU_SUBTYPE_ARM64_ALL; } if(specific_arch_flag != NULL) specific_arch_flag->name = "arm64v8"; return(1); } break; } return(0); }
/* * True if there is more of the current diff listing to process. */ bool another_hunk(void) { long line_beginning; /* file pos of the current line */ LINENUM repl_beginning; /* index of --- line */ LINENUM fillcnt; /* #lines of missing ptrn or repl */ LINENUM fillsrc; /* index of first line to copy */ LINENUM filldst; /* index of first missing line */ bool ptrn_spaces_eaten; /* ptrn was slightly misformed */ bool repl_could_be_missing; /* no + or ! lines in this hunk */ bool repl_missing; /* we are now backtracking */ long repl_backtrack_position; /* file pos of first repl line */ LINENUM repl_patch_line; /* input line number for same */ LINENUM ptrn_copiable; /* # of copiable lines in ptrn */ char *s; size_t len; int context = 0; while (p_end >= 0) { if (p_end == p_efake) p_end = p_bfake; /* don't free twice */ else free(p_line[p_end]); p_end--; } p_efake = -1; p_max = hunkmax; /* gets reduced when --- found */ if (diff_type == CONTEXT_DIFF || diff_type == NEW_CONTEXT_DIFF) { line_beginning = ftell(pfp); repl_beginning = 0; fillcnt = 0; fillsrc = 0; filldst = 0; ptrn_spaces_eaten = false; repl_could_be_missing = true; repl_missing = false; repl_backtrack_position = 0; repl_patch_line = 0; ptrn_copiable = 0; len = pgets(true); p_input_line++; if (len == 0 || strnNE(buf, "********", 8)) { next_intuit_at(line_beginning, p_input_line); return false; } p_context = 100; p_hunk_beg = p_input_line + 1; while (p_end < p_max) { line_beginning = ftell(pfp); len = pgets(true); p_input_line++; if (len == 0) { if (p_max - p_end < 4) { /* assume blank lines got chopped */ strlcpy(buf, " \n", buf_size); } else { if (repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } fatal("unexpected end of file in patch\n"); } } p_end++; if (p_end >= hunkmax) fatal("Internal error: hunk larger than hunk " "buffer size"); p_char[p_end] = *buf; p_line[p_end] = NULL; switch (*buf) { case '*': if (strnEQ(buf, "********", 8)) { if (repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } else fatal("unexpected end of hunk " "at line %ld\n", p_input_line); } if (p_end != 0) { if (repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } fatal("unexpected *** at line %ld: %s", p_input_line, buf); } context = 0; p_line[p_end] = savestr(buf); if (out_of_mem) { p_end--; return false; } for (s = buf; *s && !isdigit((unsigned char)*s); s++) ; if (!*s) malformed(); if (strnEQ(s, "0,0", 3)) memmove(s, s + 2, strlen(s + 2) + 1); p_first = (LINENUM) atol(s); while (isdigit((unsigned char)*s)) s++; if (*s == ',') { for (; *s && !isdigit((unsigned char)*s); s++) ; if (!*s) malformed(); p_ptrn_lines = ((LINENUM) atol(s)) - p_first + 1; } else if (p_first) p_ptrn_lines = 1; else { p_ptrn_lines = 0; p_first = 1; } /* we need this much at least */ p_max = p_ptrn_lines + 6; while (p_max >= hunkmax) grow_hunkmax(); p_max = hunkmax; break; case '-': if (buf[1] == '-') { if (repl_beginning || (p_end != p_ptrn_lines + 1 + (p_char[p_end - 1] == '\n'))) { if (p_end == 1) { /* * `old' lines were omitted; * set up to fill them in * from 'new' context lines. */ p_end = p_ptrn_lines + 1; fillsrc = p_end + 1; filldst = 1; fillcnt = p_ptrn_lines; } else { if (repl_beginning) { if (repl_could_be_missing) { repl_missing = true; goto hunk_done; } fatal("duplicate \"---\" at line %ld--check line numbers at line %ld\n", p_input_line, p_hunk_beg + repl_beginning); } else { fatal("%s \"---\" at line %ld--check line numbers at line %ld\n", (p_end <= p_ptrn_lines ? "Premature" : "Overdue"), p_input_line, p_hunk_beg); } } } repl_beginning = p_end; repl_backtrack_position = ftell(pfp); repl_patch_line = p_input_line; p_line[p_end] = savestr(buf); if (out_of_mem) { p_end--; return false; } p_char[p_end] = '='; for (s = buf; *s && !isdigit((unsigned char)*s); s++) ; if (!*s) malformed(); p_newfirst = (LINENUM) atol(s); while (isdigit((unsigned char)*s)) s++; if (*s == ',') { for (; *s && !isdigit((unsigned char)*s); s++) ; if (!*s) malformed(); p_repl_lines = ((LINENUM) atol(s)) - p_newfirst + 1; } else if (p_newfirst) p_repl_lines = 1; else { p_repl_lines = 0; p_newfirst = 1; } p_max = p_repl_lines + p_end; if (p_max > MAXHUNKSIZE) fatal("hunk too large (%ld lines) at line %ld: %s", p_max, p_input_line, buf); while (p_max >= hunkmax) grow_hunkmax(); if (p_repl_lines != ptrn_copiable && (p_context != 0 || p_repl_lines != 1)) repl_could_be_missing = false; break; } goto change_line; case '+': case '!': repl_could_be_missing = false; change_line: if (buf[1] == '\n' && canonicalize) strlcpy(buf + 1, " \n", buf_size - 1); if (!isspace((unsigned char)buf[1]) && buf[1] != '>' && buf[1] != '<' && repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } if (context >= 0) { if (context < p_context) p_context = context; context = -1000; } p_line[p_end] = savestr(buf + 2); if (out_of_mem) { p_end--; return false; } if (p_end == p_ptrn_lines) { if (remove_special_line()) { int l; l = strlen(p_line[p_end]) - 1; (p_line[p_end])[l] = 0; } } break; case '\t': case '\n': /* assume the 2 spaces got eaten */ if (repl_beginning && repl_could_be_missing && (!ptrn_spaces_eaten || diff_type == NEW_CONTEXT_DIFF)) { repl_missing = true; goto hunk_done; } p_line[p_end] = savestr(buf); if (out_of_mem) { p_end--; return false; } if (p_end != p_ptrn_lines + 1) { ptrn_spaces_eaten |= (repl_beginning != 0); context++; if (!repl_beginning) ptrn_copiable++; p_char[p_end] = ' '; } break; case ' ': if (!isspace((unsigned char)buf[1]) && repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } context++; if (!repl_beginning) ptrn_copiable++; p_line[p_end] = savestr(buf + 2); if (out_of_mem) { p_end--; return false; } break; default: if (repl_beginning && repl_could_be_missing) { repl_missing = true; goto hunk_done; } malformed(); } /* set up p_len for strncmp() so we don't have to */ /* assume null termination */ if (p_line[p_end]) p_len[p_end] = strlen(p_line[p_end]); else p_len[p_end] = 0; } hunk_done: if (p_end >= 0 && !repl_beginning) fatal("no --- found in patch at line %ld\n", pch_hunk_beg()); if (repl_missing) { /* reset state back to just after --- */ p_input_line = repl_patch_line; for (p_end--; p_end > repl_beginning; p_end--) free(p_line[p_end]); fseek(pfp, repl_backtrack_position, SEEK_SET); /* redundant 'new' context lines were omitted - set */ /* up to fill them in from the old file context */ if (!p_context && p_repl_lines == 1) { p_repl_lines = 0; p_max--; } fillsrc = 1; filldst = repl_beginning + 1; fillcnt = p_repl_lines; p_end = p_max; } else if (!p_context && fillcnt == 1) { /* the first hunk was a null hunk with no context */ /* and we were expecting one line -- fix it up. */ while (filldst < p_end) { p_line[filldst] = p_line[filldst + 1]; p_char[filldst] = p_char[filldst + 1]; p_len[filldst] = p_len[filldst + 1]; filldst++; } #if 0 repl_beginning--; /* this doesn't need to be fixed */ #endif p_end--; p_first++; /* do append rather than insert */ fillcnt = 0; p_ptrn_lines = 0; } if (diff_type == CONTEXT_DIFF && (fillcnt || (p_first > 1 && ptrn_copiable > 2 * p_context))) { if (verbose) say("%s\n%s\n%s\n", "(Fascinating--this is really a new-style context diff but without", "the telltale extra asterisks on the *** line that usually indicate", "the new style...)"); diff_type = NEW_CONTEXT_DIFF; } /* if there were omitted context lines, fill them in now */ if (fillcnt) { p_bfake = filldst; /* remember where not to free() */ p_efake = filldst + fillcnt - 1; while (fillcnt-- > 0) { while (fillsrc <= p_end && p_char[fillsrc] != ' ') fillsrc++; if (fillsrc > p_end) fatal("replacement text or line numbers mangled in hunk at line %ld\n", p_hunk_beg); p_line[filldst] = p_line[fillsrc]; p_char[filldst] = p_char[fillsrc]; p_len[filldst] = p_len[fillsrc]; fillsrc++; filldst++; } while (fillsrc <= p_end && fillsrc != repl_beginning && p_char[fillsrc] != ' ') fillsrc++; #ifdef DEBUGGING if (debug & 64) printf("fillsrc %ld, filldst %ld, rb %ld, e+1 %ld\n", fillsrc, filldst, repl_beginning, p_end + 1); #endif if (fillsrc != p_end + 1 && fillsrc != repl_beginning) malformed(); if (filldst != p_end + 1 && filldst != repl_beginning) malformed(); } if (p_line[p_end] != NULL) { if (remove_special_line()) { p_len[p_end] -= 1; (p_line[p_end])[p_len[p_end]] = 0; } } } else if (diff_type == UNI_DIFF) { LINENUM fillold; /* index of old lines */ LINENUM fillnew; /* index of new lines */ char ch; line_beginning = ftell(pfp); /* file pos of the current line */ len = pgets(true); p_input_line++; if (len == 0 || strnNE(buf, "@@ -", 4)) { next_intuit_at(line_beginning, p_input_line); return false; } s = buf + 4; if (!*s) malformed(); p_first = (LINENUM) atol(s); while (isdigit((unsigned char)*s)) s++; if (*s == ',') { p_ptrn_lines = (LINENUM) atol(++s); while (isdigit((unsigned char)*s)) s++; } else p_ptrn_lines = 1; if (*s == ' ') s++; if (*s != '+' || !*++s) malformed(); p_newfirst = (LINENUM) atol(s); while (isdigit((unsigned char)*s)) s++; if (*s == ',') { p_repl_lines = (LINENUM) atol(++s); while (isdigit((unsigned char)*s)) s++; } else p_repl_lines = 1; if (*s == ' ') s++; if (*s != '@') malformed(); if (!p_ptrn_lines) p_first++; /* do append rather than insert */ p_max = p_ptrn_lines + p_repl_lines + 1; while (p_max >= hunkmax) grow_hunkmax(); fillold = 1; fillnew = fillold + p_ptrn_lines; p_end = fillnew + p_repl_lines; snprintf(buf, buf_size, "*** %ld,%ld ****\n", p_first, p_first + p_ptrn_lines - 1); p_line[0] = savestr(buf); if (out_of_mem) { p_end = -1; return false; } p_char[0] = '*'; snprintf(buf, buf_size, "--- %ld,%ld ----\n", p_newfirst, p_newfirst + p_repl_lines - 1); p_line[fillnew] = savestr(buf); if (out_of_mem) { p_end = 0; return false; } p_char[fillnew++] = '='; p_context = 100; context = 0; p_hunk_beg = p_input_line + 1; while (fillold <= p_ptrn_lines || fillnew <= p_end) { line_beginning = ftell(pfp); len = pgets(true); p_input_line++; if (len == 0) { if (p_max - fillnew < 3) { /* assume blank lines got chopped */ strlcpy(buf, " \n", buf_size); } else { fatal("unexpected end of file in patch\n"); } } if (*buf == '\t' || *buf == '\n') { ch = ' '; /* assume the space got eaten */ s = savestr(buf); } else { ch = *buf; s = savestr(buf + 1); } if (out_of_mem) { while (--fillnew > p_ptrn_lines) free(p_line[fillnew]); p_end = fillold - 1; return false; } switch (ch) { case '-': if (fillold > p_ptrn_lines) { free(s); p_end = fillnew - 1; malformed(); } p_char[fillold] = ch; p_line[fillold] = s; p_len[fillold++] = strlen(s); if (fillold > p_ptrn_lines) { if (remove_special_line()) { p_len[fillold - 1] -= 1; s[p_len[fillold - 1]] = 0; } } break; case '=': ch = ' '; /* FALL THROUGH */ case ' ': if (fillold > p_ptrn_lines) { free(s); while (--fillnew > p_ptrn_lines) free(p_line[fillnew]); p_end = fillold - 1; malformed(); } context++; p_char[fillold] = ch; p_line[fillold] = s; p_len[fillold++] = strlen(s); s = savestr(s); if (out_of_mem) { while (--fillnew > p_ptrn_lines) free(p_line[fillnew]); p_end = fillold - 1; return false; } if (fillold > p_ptrn_lines) { if (remove_special_line()) { p_len[fillold - 1] -= 1; s[p_len[fillold - 1]] = 0; } } /* FALL THROUGH */ case '+': if (fillnew > p_end) { free(s); while (--fillnew > p_ptrn_lines) free(p_line[fillnew]); p_end = fillold - 1; malformed(); } p_char[fillnew] = ch; p_line[fillnew] = s; p_len[fillnew++] = strlen(s); if (fillold > p_ptrn_lines) { if (remove_special_line()) { p_len[fillnew - 1] -= 1; s[p_len[fillnew - 1]] = 0; } } break; default: p_end = fillnew; malformed(); } if (ch != ' ' && context > 0) { if (context < p_context) p_context = context; context = -1000; } } /* while */ } else { /* normal diff--fake it up */ char hunk_type; int i; LINENUM min, max; line_beginning = ftell(pfp); p_context = 0; len = pgets(true); p_input_line++; if (len == 0 || !isdigit((unsigned char)*buf)) { next_intuit_at(line_beginning, p_input_line); return false; } p_first = (LINENUM) atol(buf); for (s = buf; isdigit((unsigned char)*s); s++) ; if (*s == ',') { p_ptrn_lines = (LINENUM) atol(++s) - p_first + 1; while (isdigit((unsigned char)*s)) s++; } else p_ptrn_lines = (*s != 'a'); hunk_type = *s; if (hunk_type == 'a') p_first++; /* do append rather than insert */ min = (LINENUM) atol(++s); for (; isdigit((unsigned char)*s); s++) ; if (*s == ',') max = (LINENUM) atol(++s); else max = min; if (hunk_type == 'd') min++; p_end = p_ptrn_lines + 1 + max - min + 1; if (p_end > MAXHUNKSIZE) fatal("hunk too large (%ld lines) at line %ld: %s", p_end, p_input_line, buf); while (p_end >= hunkmax) grow_hunkmax(); p_newfirst = min; p_repl_lines = max - min + 1; snprintf(buf, buf_size, "*** %ld,%ld\n", p_first, p_first + p_ptrn_lines - 1); p_line[0] = savestr(buf); if (out_of_mem) { p_end = -1; return false; } p_char[0] = '*'; for (i = 1; i <= p_ptrn_lines; i++) { len = pgets(true); p_input_line++; if (len == 0) fatal("unexpected end of file in patch at line %ld\n", p_input_line); if (*buf != '<') fatal("< expected at line %ld of patch\n", p_input_line); p_line[i] = savestr(buf + 2); if (out_of_mem) { p_end = i - 1; return false; } p_len[i] = strlen(p_line[i]); p_char[i] = '-'; } if (remove_special_line()) { p_len[i - 1] -= 1; (p_line[i - 1])[p_len[i - 1]] = 0; } if (hunk_type == 'c') { len = pgets(true); p_input_line++; if (len == 0) fatal("unexpected end of file in patch at line %ld\n", p_input_line); if (*buf != '-') fatal("--- expected at line %ld of patch\n", p_input_line); } snprintf(buf, buf_size, "--- %ld,%ld\n", min, max); p_line[i] = savestr(buf); if (out_of_mem) { p_end = i - 1; return false; } p_char[i] = '='; for (i++; i <= p_end; i++) { len = pgets(true); p_input_line++; if (len == 0) fatal("unexpected end of file in patch at line %ld\n", p_input_line); if (*buf != '>') fatal("> expected at line %ld of patch\n", p_input_line); p_line[i] = savestr(buf + 2); if (out_of_mem) { p_end = i - 1; return false; } p_len[i] = strlen(p_line[i]); p_char[i] = '+'; } if (remove_special_line()) { p_len[i - 1] -= 1; (p_line[i - 1])[p_len[i - 1]] = 0; } } if (reverse) /* backwards patch? */ if (!pch_swap()) say("Not enough memory to swap next hunk!\n"); #ifdef DEBUGGING if (debug & 2) { int i; char special; for (i = 0; i <= p_end; i++) { if (i == p_ptrn_lines) special = '^'; else special = ' '; fprintf(stderr, "%3d %c %c %s", i, p_char[i], special, p_line[i]); fflush(stderr); } } #endif if (p_end + 1 < hunkmax)/* paranoia reigns supreme... */ p_char[p_end + 1] = '^'; /* add a stopper for apply_hunk */ return true; }
static int intuit_diff_type(void) { long this_line = 0, previous_line; long first_command_line = -1; LINENUM fcl_line = -1; bool last_line_was_command = false, this_is_a_command = false; bool stars_last_line = false, stars_this_line = false; char *s, *t; int indent, retval; struct file_name names[MAX_FILE]; memset(names, 0, sizeof(names)); ok_to_create_file = false; fseek(pfp, p_base, SEEK_SET); p_input_line = p_bline - 1; for (;;) { previous_line = this_line; last_line_was_command = this_is_a_command; stars_last_line = stars_this_line; this_line = ftell(pfp); indent = 0; p_input_line++; if (pgets(false) == 0) { if (first_command_line >= 0L) { /* nothing but deletes!? */ p_start = first_command_line; p_sline = fcl_line; retval = ED_DIFF; goto scan_exit; } else { p_start = this_line; p_sline = p_input_line; retval = 0; goto scan_exit; } } for (s = buf; *s == ' ' || *s == '\t' || *s == 'X'; s++) { if (*s == '\t') indent += 8 - (indent % 8); else indent++; } for (t = s; isdigit((unsigned char)*t) || *t == ','; t++) ; this_is_a_command = (isdigit((unsigned char)*s) && (*t == 'd' || *t == 'c' || *t == 'a')); if (first_command_line < 0L && this_is_a_command) { first_command_line = this_line; fcl_line = p_input_line; p_indent = indent; /* assume this for now */ } if (!stars_last_line && strnEQ(s, "*** ", 4)) names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath); else if (strnEQ(s, "--- ", 4)) names[NEW_FILE].path = fetchname(s + 4, &names[NEW_FILE].exists, strippath); else if (strnEQ(s, "+++ ", 4)) /* pretend it is the old name */ names[OLD_FILE].path = fetchname(s + 4, &names[OLD_FILE].exists, strippath); else if (strnEQ(s, "Index:", 6)) names[INDEX_FILE].path = fetchname(s + 6, &names[INDEX_FILE].exists, strippath); else if (strnEQ(s, "Prereq:", 7)) { for (t = s + 7; isspace((unsigned char)*t); t++) ; revision = savestr(t); for (t = revision; *t && !isspace((unsigned char)*t); t++) ; *t = '\0'; if (*revision == '\0') { free(revision); revision = NULL; } } else if (strnEQ(s, "==== ", 5)) { /* Perforce-style diffs. */ if ((t = strstr(s + 5, " - ")) != NULL) p4_fetchname(&names[NEW_FILE], t + 3); p4_fetchname(&names[OLD_FILE], s + 5); } if ((!diff_type || diff_type == ED_DIFF) && first_command_line >= 0L && strEQ(s, ".\n")) { p_indent = indent; p_start = first_command_line; p_sline = fcl_line; retval = ED_DIFF; goto scan_exit; } if ((!diff_type || diff_type == UNI_DIFF) && strnEQ(s, "@@ -", 4)) { if (strnEQ(s + 4, "0,0", 3)) ok_to_create_file = true; p_indent = indent; p_start = this_line; p_sline = p_input_line; retval = UNI_DIFF; goto scan_exit; } stars_this_line = strnEQ(s, "********", 8); if ((!diff_type || diff_type == CONTEXT_DIFF) && stars_last_line && strnEQ(s, "*** ", 4)) { if (atol(s + 4) == 0) ok_to_create_file = true; /* * If this is a new context diff the character just * before the newline is a '*'. */ while (*s != '\n') s++; p_indent = indent; p_start = previous_line; p_sline = p_input_line - 1; retval = (*(s - 1) == '*' ? NEW_CONTEXT_DIFF : CONTEXT_DIFF); goto scan_exit; } if ((!diff_type || diff_type == NORMAL_DIFF) && last_line_was_command && (strnEQ(s, "< ", 2) || strnEQ(s, "> ", 2))) { p_start = previous_line; p_sline = p_input_line - 1; p_indent = indent; retval = NORMAL_DIFF; goto scan_exit; } } scan_exit: if (retval == UNI_DIFF) { /* unswap old and new */ struct file_name tmp = names[OLD_FILE]; names[OLD_FILE] = names[NEW_FILE]; names[NEW_FILE] = tmp; } if (filearg[0] == NULL) { if (posix) filearg[0] = posix_name(names, ok_to_create_file); else { /* Ignore the Index: name for context diffs, like GNU */ if (names[OLD_FILE].path != NULL || names[NEW_FILE].path != NULL) { free(names[INDEX_FILE].path); names[INDEX_FILE].path = NULL; } filearg[0] = best_name(names, ok_to_create_file); } } free(bestguess); bestguess = NULL; if (filearg[0] != NULL) bestguess = savestr(filearg[0]); else if (!ok_to_create_file) { /* * We don't want to create a new file but we need a * filename to set bestguess. Avoid setting filearg[0] * so the file is not created automatically. */ if (posix) bestguess = posix_name(names, true); else bestguess = best_name(names, true); } free(names[OLD_FILE].path); free(names[NEW_FILE].path); free(names[INDEX_FILE].path); return retval; }
FILE * collect(struct header *hp, int printheaders) { FILE *fbuf; int lc, cc, fd, c, t, lastlong, rc, sig; int escape, eofcount, longline; char getsub; char linebuf[LINESIZE], tempname[PATHSIZE], *cp; collf = NULL; eofcount = 0; hadintr = 0; lastlong = 0; longline = 0; if ((cp = value("escape")) != NULL) escape = *cp; else escape = ESCAPE; noreset++; (void)snprintf(tempname, sizeof(tempname), "%s/mail.RsXXXXXXXXXX", tmpdir); if ((fd = mkstemp(tempname)) == -1 || (collf = Fdopen(fd, "w+")) == NULL) { warn("%s", tempname); goto err; } (void)rm(tempname); /* * If we are going to prompt for a subject, * refrain from printing a newline after * the headers (since some people mind). */ t = GTO|GSUBJECT|GCC|GNL; getsub = 0; if (hp->h_subject == NULL && value("interactive") != NULL && (value("ask") != NULL || value("asksub") != NULL)) t &= ~GNL, getsub++; if (printheaders) { puthead(hp, stdout, t); fflush(stdout); } if (getsub && gethfromtty(hp, GSUBJECT) == -1) goto err; if (0) { cont: /* Come here for printing the after-suspend message. */ if (isatty(0)) { puts("(continue)"); fflush(stdout); } } for (;;) { c = readline(stdin, linebuf, LINESIZE, &sig); /* Act on any signal caught during readline() ignoring 'c' */ switch (sig) { case 0: break; case SIGINT: if (collabort()) goto err; continue; case SIGHUP: rewind(collf); savedeadletter(collf); /* * Let's pretend nobody else wants to clean up, * a true statement at this time. */ exit(1); default: /* Stopped due to job control */ (void)kill(0, sig); goto cont; } /* No signal, check for error */ if (c < 0) { if (value("interactive") != NULL && value("ignoreeof") != NULL && ++eofcount < 25) { puts("Use \".\" to terminate letter"); continue; } break; } lastlong = longline; longline = (c == LINESIZE - 1); eofcount = 0; hadintr = 0; if (linebuf[0] == '.' && linebuf[1] == '\0' && value("interactive") != NULL && !lastlong && (value("dot") != NULL || value("ignoreeof") != NULL)) break; if (linebuf[0] != escape || value("interactive") == NULL || lastlong) { if (putline(collf, linebuf, !longline) < 0) goto err; continue; } c = linebuf[1]; switch (c) { default: /* * On double escape, just send the single one. * Otherwise, it's an error. */ if (c == escape) { if (putline(collf, &linebuf[1], !longline) < 0) goto err; else break; } puts("Unknown tilde escape."); break; case '!': /* * Shell escape, send the balance of the * line to sh -c. */ shell(&linebuf[2]); break; case ':': case '_': /* * Escape to command mode, but be nice! */ execute(&linebuf[2], 1); goto cont; case '.': /* * Simulate end of file on input. */ goto out; case 'q': /* * Force a quit of sending mail. * Act like an interrupt happened. */ hadintr++; collabort(); fputs("Interrupt\n", stderr); goto err; case 'x': /* * Force a quit of sending mail. * Do not save the message. */ goto err; case 'h': /* * Grab a bunch of headers. */ grabh(hp, GTO|GSUBJECT|GCC|GBCC); goto cont; case 't': /* * Add to the To list. */ hp->h_to = cat(hp->h_to, extract(&linebuf[2], GTO)); break; case 's': /* * Set the Subject list. */ cp = &linebuf[2]; while (isspace(*cp)) cp++; hp->h_subject = savestr(cp); break; case 'c': /* * Add to the CC list. */ hp->h_cc = cat(hp->h_cc, extract(&linebuf[2], GCC)); break; case 'b': /* * Add stuff to blind carbon copies list. */ hp->h_bcc = cat(hp->h_bcc, extract(&linebuf[2], GBCC)); break; case 'd': linebuf[2] = '\0'; strlcat(linebuf, getdeadletter(), sizeof(linebuf)); /* fall into . . . */ case 'r': case '<': /* * Invoke a file: * Search for the file name, * then open it and copy the contents to collf. */ cp = &linebuf[2]; while (isspace(*cp)) cp++; if (*cp == '\0') { puts("Interpolate what file?"); break; } cp = expand(cp); if (cp == NULL) break; if (isdir(cp)) { printf("%s: Directory\n", cp); break; } if ((fbuf = Fopen(cp, "r")) == NULL) { warn("%s", cp); break; } printf("\"%s\" ", cp); fflush(stdout); lc = 0; cc = 0; while ((rc = readline(fbuf, linebuf, LINESIZE, NULL)) >= 0) { if (rc != LINESIZE - 1) lc++; if ((t = putline(collf, linebuf, rc != LINESIZE-1)) < 0) { (void)Fclose(fbuf); goto err; } cc += t; } (void)Fclose(fbuf); printf("%d/%d\n", lc, cc); break; case 'w': /* * Write the message on a file. */ cp = &linebuf[2]; while (*cp == ' ' || *cp == '\t') cp++; if (*cp == '\0') { fputs("Write what file!?\n", stderr); break; } if ((cp = expand(cp)) == NULL) break; rewind(collf); exwrite(cp, collf, 1); break; case 'm': case 'M': case 'f': case 'F': /* * Interpolate the named messages, if we * are in receiving mail mode. Does the * standard list processing garbage. * If ~f is given, we don't shift over. */ if (forward(linebuf + 2, collf, tempname, c) < 0) goto err; goto cont; case '?': if ((fbuf = Fopen(_PATH_TILDE, "r")) == NULL) { warn(_PATH_TILDE); break; } while ((t = getc(fbuf)) != EOF) (void)putchar(t); (void)Fclose(fbuf); break; case 'p': /* * Print out the current state of the * message without altering anything. */ rewind(collf); puts("-------\nMessage contains:"); puthead(hp, stdout, GTO|GSUBJECT|GCC|GBCC|GNL); while ((t = getc(collf)) != EOF) (void)putchar(t); goto cont; case '|': /* * Pipe message through command. * Collect output as new message. */ rewind(collf); mespipe(collf, &linebuf[2]); goto cont; case 'v': case 'e': /* * Edit the current message. * 'e' means to use EDITOR * 'v' means to use VISUAL */ rewind(collf); mesedit(collf, c); goto cont; } } if (value("interactive") != NULL) { if (value("askcc") != NULL || value("askbcc") != NULL) { if (value("askcc") != NULL) { if (gethfromtty(hp, GCC) == -1) goto err; } if (value("askbcc") != NULL) { if (gethfromtty(hp, GBCC) == -1) goto err; } } else { puts("EOT"); (void)fflush(stdout); } } goto out; err: if (collf != NULL) { (void)Fclose(collf); collf = NULL; } out: if (collf != NULL) rewind(collf); noreset--; return(collf); }
char * safeexpand(char name[]) { char *t = expand(name); return (t) ? t : savestr(name); }