|
|
1.1 root 1: #include <stdio.h>
2: #include <string.h>
3: #include <malloc.h>
4: #include <pwd.h>
5:
6: #define OPTS "a:m:o:q:wxyDSVdef:mpr#"
7: #define MAILX "/bin/mail"
8: #define UPDATE path("update")
9: #define DBINFO path("dbinfo")
10: #define DELPAP "del=p"
11: #define ALLYES "all=y"
12: #define ASKYES "ask=y"
13:
14: #define PREMA(e) printf("%s%s", e, yflg ? ", " : "\n")
15: #define PRMULT(m, p) PREMA(m[*m[EMAIL] && !p ? EMAIL : PAPER])
16:
17: #define WHO 0
18: #define EMAIL 1
19: #define PAPER 2
20: #define NARGS 3
21: #define MULT 10
22:
23: typedef char *strings[512];
24: typedef char buffer[BUFSIZ];
25:
26: char usage[] = "usage:\
27: post [-a attr] [-m mods] [-o fmt] [-q query]\n\
28: [-w] [mail options] [addresses...]\n\
29: [-D] [-S] [-V]\n";
30:
31: strings qdef;
32: strings postattr;
33: buffer postofmt;
34: int postetc;
35: int wflg, xflg, yflg;
36: int askyes = 0;
37: int exitval = 0;
38: char *mult[MULT][NARGS];
39: char *pq;
40: void resolve();
41:
42: extern char emp_fmt[], ema_fmt[], who_fmt[];
43: extern char emp_def[], emp_seq[], emp_uni[];
44: extern char *pq_open();
45: extern char *getenv(), *strdup();
46: struct passwd *getpwnam();
47:
48: char *ofmt = emp_fmt, *attr = emp_def, *mods = "", *qopt = "";
49:
50: main(argc, argv)
51: int argc;
52: char *argv[];
53: {
54: extern char *optarg;
55: extern int optind;
56: strings args;
57: buffer buf;
58: char **ap = args;
59: int c;
60:
61: *ap++ = argv[0];
62:
63: while ((c = getopt(argc, argv, OPTS)) != EOF)
64: switch (c) {
65: case 'a':
66: attr = optarg;
67: break;
68: case 'm':
69: mods = optarg;
70: break;
71: case 'o':
72: ofmt = optarg;
73: break;
74: case 'q':
75: qopt = optarg;
76: break;
77: case 'w':
78: wflg++;
79: break;
80: case 'x':
81: xflg++;
82: break;
83: case 'y':
84: yflg++;
85: break;
86: case 'D':
87: execvp(DBINFO, argv);
88: perror(DBINFO);
89: return 1;
90: case 'S':
91: execvp(UPDATE, argv);
92: perror(UPDATE);
93: return 1;
94: case 'V':
95: puts("research post 4.0 9/1/88");
96: return 1;
97: case '?':
98: fputs(usage, stderr);
99: return 1;
100: default:
101: sprintf(*ap++ = malloc(3), "-%c", c);
102: if (optarg)
103: *ap++ = optarg;
104: }
105:
106: if (!wflg && !xflg && !yflg) {
107: while (optind < argc)
108: *ap++ = argv[optind++];
109: *ap++ = 0;
110: execv(MAILX, args);
111: perror(MAILX);
112: return 1;
113: }
114: if (xflg || yflg) {
115: strcpy(buf, ofmt);
116: strcat(buf, ema_fmt);
117: ofmt = buf;
118: }
119:
120: postetc = !!getenv("POSTETC");
121: strvec(attr, postattr, "/:");
122: fmtcomp(postofmt, ofmt, qdef);
123: smerge(getenv("POSTQUAL"), qdef);
124: smerge(qopt, qdef);
125:
126: if (option(ASKYES, qdef))
127: askyes++;
128: if (xflg || yflg)
129: smerge(emp_uni, qdef);
130:
131: if (wflg && optind == argc)
132: argv[argc++] = "";
133: while (optind < argc) {
134: resolve(argv[optind++]);
135: if (yflg)
136: putchar('\n');
137: }
138: if (pq && pq_close(pq) == -1)
139: pqerr("pq");
140: return yflg ? 0 : exitval;
141: }
142:
143: void
144: resolve(name)
145: char *name;
146: {
147: strings q, n, rec;
148: int delpap, allyes;
149: int c, r;
150: char *p;
151: buffer out;
152:
153: p = strpbrk(name, "!@%/:=");
154: if (*name && strchr("+|", *name) || p && !strchr("/:=", *p)
155: || !p && !strpbrk(name, "._") && postetc && getpwnam(name)) {
156: PREMA(name);
157: return;
158: }
159:
160: if (!dodef(name, n, postattr)) {
161: eomatch(0, 0, 0, name);
162: return;
163: }
164: for (c = 0; q[c] = qdef[c]; c++);
165: merge(n, q);
166: delpap = option(DELPAP, q);
167: allyes = option(ALLYES, q);
168: if (option(ASKYES, q))
169: askyes++;
170:
171: c = 0;
172: if ((r = pqowrite(q)) != -1) {
173: while ((r = pq_read(pq, rec)) > 0) {
174: fmtexec(out, postofmt, rec);
175: if (match(c++, out, delpap, allyes, name, q))
176: return;
177: }
178: if (r == -1)
179: pqerr(name);
180: } else
181: pqerr(name);
182:
183: if (c == 0 && r == 0)
184: fprintf(stderr, "post: %s: Not found\n", name);
185: eomatch(c, delpap, allyes, name);
186: }
187:
188: dodef(name, vars, defs)
189: char *name;
190: strings vars, defs;
191: {
192: static buffer tmp, buf;
193: register char *bp = buf;
194: register int m, i, c;
195:
196: strcpy(tmp, name);
197: strvec(tmp, vars, "/:");
198: for (m = 0; defs[m]; m++);
199:
200: for (i = 0; vars[i]; i++)
201: if (!strchr(vars[i], '='))
202: if (i < m) {
203: c = sprintf(bp, "%s=%s", defs[i], vars[i]);
204: vars[i] = bp;
205: bp += c + 1;
206: } else {
207: fprintf(stderr, "post: %s: %s: No attribute\n",
208: name, vars[i]);
209: return 0;
210: }
211: return 1;
212: }
213:
214: match(c, out, delpap, allyes, name, q)
215: int c;
216: char *out;
217: int delpap, allyes;
218: char *name;
219: strings q;
220: {
221: buffer buf;
222: int i, m = c % MULT;
223: char *s;
224:
225: if (wflg) {
226: fputs(out, stdout);
227: return 0;
228: }
229:
230: s = strdup(out);
231: for (i = 0; i < NARGS && (mult[m][i] = s); i++)
232: if (s = strchr(s, '|'))
233: *s++ = 0;
234: skname(mult[m][PAPER]);
235: if (s = strchr(mult[m][EMAIL], '('))
236: if (xflg)
237: *--s = 0;
238: else
239: prname(s);
240:
241: if (allyes) {
242: if (xflg) {
243: PRMULT(mult[m], delpap);
244: return 0;
245: }
246: if (yflg) {
247: s = buf;
248: s += sprintf(s, "!");
249: for (i = 0; q[i]; i++)
250: if (strchr(q[i], '=') && strcmp(q[i], emp_uni))
251: s += sprintf(s, "%s:", q[i]);
252: if (delpap)
253: s += sprintf(s, "%s:", DELPAP);
254: strcpy(s, ALLYES);
255: PREMA(buf);
256: return 1;
257: }
258: }
259: if (++m < MULT)
260: return 0;
261: return session(c, m, delpap, name);
262: }
263:
264: eomatch(c, delpap, allyes, name)
265: int c, delpap, allyes;
266: char *name;
267: {
268: if (wflg || (xflg && allyes && c > 0))
269: return 1;
270: if (c == 1) {
271: PRMULT(mult[0], delpap);
272: return 1;
273: }
274: session(c, c % MULT, delpap, name);
275: }
276:
277: session(c, m, delpap, name)
278: int c, m, delpap;
279: char *name;
280: {
281: strings addr;
282: buffer ans;
283: int i;
284:
285: if (c > 0 && c < MULT)
286: fprintf(stderr, "post: %s: Ambiguous\n", name);
287: for (i = 0; i < m; i++)
288: fprintf(stderr, "%d %s\n", i, mult[i][WHO]);
289: if (xflg || !isatty(0))
290: exit(1);
291:
292: for (;;) {
293: fprintf(stderr, "Which one? [");
294: if (m > 0)
295: fprintf(stderr, "0-%d, ", m-1);
296: if (m == MULT)
297: fprintf(stderr, "CR(more), ");
298: fprintf(stderr, "o(mit), new address(es), q(uit)] ");
299:
300: if (!fgets(ans, sizeof ans, stdin))
301: exit(1);
302: ans[strlen(ans)-1] = 0;
303: if (strlen(ans) <= 1)
304: switch (*ans) {
305: case 'o':
306: return 1;
307: case 'q':
308: exit(1);
309: case 0:
310: if (m == MULT)
311: return 0;
312: else
313: continue;
314: default:
315: i = *ans - '0';
316: if (i >= 0 && i < m) {
317: PRMULT(mult[i], delpap);
318: return 1;
319: }
320: }
321:
322: strvec(ans, addr, " \t\n");
323: for (i = 0; addr[i]; i++)
324: resolve(addr[i]);
325: return 1;
326: }
327: }
328:
329: merge(qs, qd)
330: strings qs, qd;
331: {
332: int i, j, l, m;
333: char *s;
334:
335: for (l = m = 0; qd[l]; l++, m++);
336: for (i = 0; qs[i]; i++) {
337: for (j = 0; j < l; j++)
338: if ((s = strchr(qd[j], '='))
339: && !strncmp(qs[i], qd[j], s-qd[j]+1)) {
340: qd[j--] = qd[--l];
341: qd[l] = qd[--m];
342: }
343: qd[m++] = qs[i];
344: }
345: qd[m] = 0;
346: }
347:
348: smerge(s, qd)
349: char *s;
350: strings qd;
351: {
352: strings qs;
353:
354: if (s) {
355: strvec(s, qs, "/:");
356: merge(qs, qd);
357: }
358: }
359:
360: option(a, q)
361: char *a;
362: strings q;
363: {
364: char *s = strchr(a, '=');
365: int i, m, rv = 0;
366:
367: for (m = 0; q[m]; m++);
368: for (i = 0; i < m; i++)
369: if (!strncmp(q[i], a, s-a+1)) {
370: if (!strncmp(q[i], a, strlen(a)))
371: rv++;
372: q[i--] = q[--m];
373: }
374: q[m] = 0;
375: return rv;
376: }
377:
378: pqowrite(q)
379: strings q;
380: {
381: static tried = 0;
382: strings argv;
383:
384: if (!tried++) {
385: strvec(mods, argv, " \t\n");
386: pq = pq_open(argv);
387: }
388: return pq ? pq_write(pq, q) : -1;
389: }
390:
391: pqerr(msg)
392: char *msg;
393: {
394: extern char pq_error[];
395: fprintf(stderr, "post: %s: %s\n", msg, pq_error);
396: exitval++;
397: }
398:
399: prname(s)
400: char *s;
401: {
402: for (; *s; s++)
403: if (*s == '_') {
404: if (s[1] == '_')
405: *s++ = ',';
406: *s = ' ';
407: }
408: }
409:
410: skname(s)
411: char *s;
412: {
413: char *ns;
414:
415: for (ns = s; *s; s++)
416: if (*s != ' ' && *s != '\'')
417: *ns++ = *s;
418: *ns = 0;
419: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.