Commit | Line | Data |
---|---|---|
d185cb11 DF |
1 | /* |
2 | ** Sendmail | |
3 | ** Copyright (c) 1983 Eric P. Allman | |
4 | ** Berkeley, California | |
5 | ** | |
6 | ** Copyright (c) 1983 Regents of the University of California. | |
7 | ** All rights reserved. The Berkeley software License Agreement | |
8 | ** specifies the terms and conditions for redistribution. | |
9 | */ | |
10 | ||
11 | #ifndef lint | |
9da8ffc8 | 12 | static char SccsId[] = "@(#)conf.c 5.14 (Berkeley) %G%"; |
d185cb11 DF |
13 | #endif not lint |
14 | ||
b3cbe40f | 15 | # include <pwd.h> |
d209c154 | 16 | # include <sys/ioctl.h> |
2e3062fe EA |
17 | # ifdef sun |
18 | # include <sys/param.h> | |
19 | # endif sun | |
96faada8 | 20 | # include "sendmail.h" |
916b3375 | 21 | |
b3cbe40f | 22 | /* |
96faada8 | 23 | ** CONF.C -- Sendmail Configuration Tables. |
b3cbe40f EA |
24 | ** |
25 | ** Defines the configuration of this installation. | |
26 | ** | |
cb590f52 | 27 | ** Compilation Flags: |
cb590f52 EA |
28 | ** V6 -- running on a version 6 system. This determines |
29 | ** whether to define certain routines between | |
30 | ** the two systems. If you are running a funny | |
31 | ** system, e.g., V6 with long tty names, this | |
32 | ** should be checked carefully. | |
f7e74083 | 33 | ** VMUNIX -- running on a Berkeley UNIX system. |
b3cbe40f | 34 | ** |
cb590f52 | 35 | ** Configuration Variables: |
1a12c7d6 EA |
36 | ** HdrInfo -- a table describing well-known header fields. |
37 | ** Each entry has the field name and some flags, | |
df960d9b | 38 | ** which are described in sendmail.h. |
9c6d4c70 EA |
39 | ** |
40 | ** Notes: | |
41 | ** I have tried to put almost all the reasonable | |
42 | ** configuration information into the configuration | |
43 | ** file read at runtime. My intent is that anything | |
44 | ** here is a function of the version of UNIX you | |
45 | ** are running, or is really static -- for example | |
46 | ** the headers are a superset of widely used | |
47 | ** protocols. If you find yourself playing with | |
48 | ** this file too much, you may be making a mistake! | |
b3cbe40f EA |
49 | */ |
50 | ||
51 | ||
52 | ||
53 | ||
b5fd168f | 54 | \f/* |
1a12c7d6 | 55 | ** Header info table |
355a2a04 | 56 | ** Final (null) entry contains the flags used for any other field. |
df960d9b EA |
57 | ** |
58 | ** Not all of these are actually handled specially by sendmail | |
59 | ** at this time. They are included as placeholders, to let | |
60 | ** you know that "someday" I intend to have sendmail do | |
61 | ** something with them. | |
1a12c7d6 EA |
62 | */ |
63 | ||
64 | struct hdrinfo HdrInfo[] = | |
65 | { | |
6144e1d1 | 66 | /* originator fields, most to least significant */ |
a90807d8 EA |
67 | "resent-sender", H_FROM|H_RESENT, |
68 | "resent-from", H_FROM|H_RESENT, | |
4e969be0 | 69 | "resent-reply-to", H_FROM|H_RESENT, |
be2fcca9 EA |
70 | "sender", H_FROM, |
71 | "from", H_FROM, | |
4e969be0 | 72 | "reply-to", H_FROM, |
be2fcca9 EA |
73 | "full-name", H_ACHECK, |
74 | "return-receipt-to", H_FROM, | |
75 | "errors-to", H_FROM, | |
6144e1d1 | 76 | /* destination fields */ |
be2fcca9 | 77 | "to", H_RCPT, |
a90807d8 | 78 | "resent-to", H_RCPT|H_RESENT, |
be2fcca9 | 79 | "cc", H_RCPT, |
a90807d8 | 80 | "resent-cc", H_RCPT|H_RESENT, |
be2fcca9 | 81 | "bcc", H_RCPT|H_ACHECK, |
a90807d8 | 82 | "resent-bcc", H_RCPT|H_ACHECK|H_RESENT, |
6144e1d1 | 83 | /* message identification and control */ |
a90807d8 EA |
84 | "message-id", 0, |
85 | "resent-message-id", H_RESENT, | |
be2fcca9 EA |
86 | "message", H_EOH, |
87 | "text", H_EOH, | |
a90807d8 EA |
88 | /* date fields */ |
89 | "date", 0, | |
90 | "resent-date", H_RESENT, | |
6144e1d1 | 91 | /* trace fields */ |
be2fcca9 EA |
92 | "received", H_TRACE|H_FORCE, |
93 | "via", H_TRACE|H_FORCE, | |
94 | "mail-from", H_TRACE|H_FORCE, | |
6144e1d1 | 95 | |
be2fcca9 | 96 | NULL, 0, |
1a12c7d6 | 97 | }; |
15b28570 EA |
98 | |
99 | ||
100 | /* | |
101 | ** ARPANET error message numbers. | |
102 | */ | |
103 | ||
314d2f52 EA |
104 | char Arpa_Info[] = "050"; /* arbitrary info */ |
105 | char Arpa_TSyserr[] = "451"; /* some (transient) system error */ | |
106 | char Arpa_PSyserr[] = "554"; /* some (permanent) system error */ | |
107 | char Arpa_Usrerr[] = "554"; /* some (fatal) user error */ | |
4e1f4d4b EA |
108 | |
109 | ||
110 | ||
4e1f4d4b EA |
111 | /* |
112 | ** Location of system files/databases/etc. | |
113 | */ | |
114 | ||
4e1f4d4b | 115 | char *ConfFile = "/usr/lib/sendmail.cf"; /* runtime configuration */ |
acae5a9d EA |
116 | char *FreezeFile = "/usr/lib/sendmail.fc"; /* frozen version of above */ |
117 | ||
118 | ||
1744384a EA |
119 | |
120 | /* | |
2e3062fe | 121 | ** Miscellaneous stuff. |
1744384a EA |
122 | */ |
123 | ||
2e3062fe EA |
124 | int DtableSize = 50; /* max open files; reset in 4.2bsd */ |
125 | \f/* | |
126 | ** SETDEFAULTS -- set default values | |
127 | ** | |
128 | ** Because of the way freezing is done, these must be initialized | |
129 | ** using direct code. | |
130 | ** | |
131 | ** Parameters: | |
132 | ** none. | |
133 | ** | |
134 | ** Returns: | |
135 | ** none. | |
136 | ** | |
137 | ** Side Effects: | |
138 | ** Initializes a bunch of global variables to their | |
139 | ** default values. | |
140 | */ | |
141 | ||
142 | setdefaults() | |
143 | { | |
144 | QueueLA = 8; | |
145 | QueueFactor = 10000; | |
146 | RefuseLA = 12; | |
147 | SpaceSub = ' '; | |
a0225d08 EA |
148 | WkRecipFact = 1000; |
149 | WkClassFact = 1800; | |
9da8ffc8 | 150 | WkTimeFact = 9000; |
a0225d08 EA |
151 | FileMode = 0644; |
152 | DefUid = 1; | |
153 | DefGid = 1; | |
2e3062fe | 154 | } |
b3cbe40f EA |
155 | \f |
156 | # ifdef V6 | |
157 | /* | |
14e42c2b | 158 | ** TTYNAME -- return name of terminal. |
b3cbe40f EA |
159 | ** |
160 | ** Parameters: | |
14e42c2b | 161 | ** fd -- file descriptor to check. |
b3cbe40f EA |
162 | ** |
163 | ** Returns: | |
14e42c2b EA |
164 | ** pointer to full path of tty. |
165 | ** NULL if no tty. | |
b3cbe40f EA |
166 | ** |
167 | ** Side Effects: | |
168 | ** none. | |
b3cbe40f EA |
169 | */ |
170 | ||
b3cbe40f | 171 | char * |
14e42c2b EA |
172 | ttyname(fd) |
173 | int fd; | |
b3cbe40f | 174 | { |
14e42c2b | 175 | register char tn; |
b3cbe40f | 176 | static char pathn[] = "/dev/ttyx"; |
b3cbe40f EA |
177 | |
178 | /* compute the pathname of the controlling tty */ | |
14e42c2b | 179 | if ((tn = ttyn(fd)) == NULL) |
b3cbe40f EA |
180 | { |
181 | errno = 0; | |
182 | return (NULL); | |
183 | } | |
14e42c2b | 184 | pathn[8] = tn; |
b3cbe40f EA |
185 | return (pathn); |
186 | } | |
187 | \f/* | |
188 | ** FDOPEN -- Open a stdio file given an open file descriptor. | |
189 | ** | |
190 | ** This is included here because it is standard in v7, but we | |
191 | ** need it in v6. | |
192 | ** | |
193 | ** Algorithm: | |
194 | ** Open /dev/null to create a descriptor. | |
195 | ** Close that descriptor. | |
196 | ** Copy the existing fd into the descriptor. | |
197 | ** | |
198 | ** Parameters: | |
199 | ** fd -- the open file descriptor. | |
200 | ** type -- "r", "w", or whatever. | |
201 | ** | |
202 | ** Returns: | |
203 | ** The file descriptor it creates. | |
204 | ** | |
205 | ** Side Effects: | |
206 | ** none | |
207 | ** | |
b3cbe40f EA |
208 | ** Called By: |
209 | ** deliver | |
210 | ** | |
211 | ** Notes: | |
212 | ** The mode of fd must match "type". | |
213 | */ | |
214 | ||
215 | FILE * | |
216 | fdopen(fd, type) | |
217 | int fd; | |
218 | char *type; | |
219 | { | |
220 | register FILE *f; | |
221 | ||
222 | f = fopen("/dev/null", type); | |
29871fef | 223 | (void) close(fileno(f)); |
b3cbe40f EA |
224 | fileno(f) = fd; |
225 | return (f); | |
226 | } | |
227 | \f/* | |
228 | ** INDEX -- Return pointer to character in string | |
229 | ** | |
230 | ** For V7 compatibility. | |
231 | ** | |
232 | ** Parameters: | |
233 | ** s -- a string to scan. | |
234 | ** c -- a character to look for. | |
235 | ** | |
236 | ** Returns: | |
237 | ** If c is in s, returns the address of the first | |
238 | ** instance of c in s. | |
239 | ** NULL if c is not in s. | |
240 | ** | |
241 | ** Side Effects: | |
242 | ** none. | |
b3cbe40f EA |
243 | */ |
244 | ||
b14547d5 | 245 | char * |
b3cbe40f EA |
246 | index(s, c) |
247 | register char *s; | |
248 | register char c; | |
249 | { | |
250 | while (*s != '\0') | |
251 | { | |
252 | if (*s++ == c) | |
253 | return (--s); | |
254 | } | |
255 | return (NULL); | |
256 | } | |
a0554f81 EA |
257 | \f/* |
258 | ** UMASK -- fake the umask system call. | |
259 | ** | |
260 | ** Since V6 always acts like the umask is zero, we will just | |
261 | ** assume the same thing. | |
262 | */ | |
263 | ||
264 | /*ARGSUSED*/ | |
265 | umask(nmask) | |
266 | { | |
267 | return (0); | |
268 | } | |
269 | ||
270 | ||
271 | /* | |
272 | ** GETRUID -- get real user id. | |
273 | */ | |
274 | ||
275 | getruid() | |
276 | { | |
277 | return (getuid() & 0377); | |
278 | } | |
279 | ||
280 | ||
281 | /* | |
282 | ** GETRGID -- get real group id. | |
283 | */ | |
284 | ||
285 | getrgid() | |
286 | { | |
287 | return (getgid() & 0377); | |
288 | } | |
289 | ||
290 | ||
291 | /* | |
292 | ** GETEUID -- get effective user id. | |
293 | */ | |
294 | ||
295 | geteuid() | |
296 | { | |
297 | return ((getuid() >> 8) & 0377); | |
298 | } | |
299 | ||
300 | ||
301 | /* | |
302 | ** GETEGID -- get effective group id. | |
303 | */ | |
304 | ||
305 | getegid() | |
306 | { | |
307 | return ((getgid() >> 8) & 0377); | |
308 | } | |
309 | ||
310 | # endif V6 | |
311 | \f | |
312 | # ifndef V6 | |
313 | ||
314 | /* | |
315 | ** GETRUID -- get real user id (V7) | |
316 | */ | |
317 | ||
318 | getruid() | |
319 | { | |
75f95954 | 320 | if (OpMode == MD_DAEMON) |
f6a0cc15 EA |
321 | return (RealUid); |
322 | else | |
323 | return (getuid()); | |
a0554f81 EA |
324 | } |
325 | ||
326 | ||
327 | /* | |
328 | ** GETRGID -- get real group id (V7). | |
329 | */ | |
330 | ||
331 | getrgid() | |
332 | { | |
75f95954 | 333 | if (OpMode == MD_DAEMON) |
f6a0cc15 EA |
334 | return (RealGid); |
335 | else | |
336 | return (getgid()); | |
a0554f81 EA |
337 | } |
338 | ||
b3cbe40f | 339 | # endif V6 |
14e42c2b | 340 | \f/* |
7338e3d4 EA |
341 | ** USERNAME -- return the user id of the logged in user. |
342 | ** | |
343 | ** Parameters: | |
344 | ** none. | |
345 | ** | |
346 | ** Returns: | |
347 | ** The login name of the logged in user. | |
348 | ** | |
349 | ** Side Effects: | |
350 | ** none. | |
351 | ** | |
352 | ** Notes: | |
353 | ** The return value is statically allocated. | |
354 | */ | |
355 | ||
356 | char * | |
357 | username() | |
358 | { | |
560a80d9 | 359 | static char *myname = NULL; |
7338e3d4 | 360 | extern char *getlogin(); |
19c3b81a MAN |
361 | register struct passwd *pw; |
362 | extern struct passwd *getpwuid(); | |
7338e3d4 | 363 | |
560a80d9 EA |
364 | /* cache the result */ |
365 | if (myname == NULL) | |
366 | { | |
367 | myname = getlogin(); | |
368 | if (myname == NULL || myname[0] == '\0') | |
369 | { | |
560a80d9 EA |
370 | |
371 | pw = getpwuid(getruid()); | |
372 | if (pw != NULL) | |
373 | myname = pw->pw_name; | |
374 | } | |
19c3b81a MAN |
375 | else |
376 | { | |
1a626eeb MAN |
377 | |
378 | pw = getpwnam(myname); | |
19c3b81a MAN |
379 | if(getuid() != pw->pw_uid) |
380 | { | |
1a626eeb | 381 | pw = getpwuid(getuid()); |
84f20e6d MAN |
382 | if (pw != NULL) |
383 | myname = pw->pw_name; | |
1a626eeb MAN |
384 | } |
385 | } | |
560a80d9 EA |
386 | if (myname == NULL || myname[0] == '\0') |
387 | { | |
388 | syserr("Who are you?"); | |
389 | myname = "postmaster"; | |
390 | } | |
391 | } | |
392 | ||
393 | return (myname); | |
7338e3d4 EA |
394 | } |
395 | \f/* | |
14e42c2b | 396 | ** TTYPATH -- Get the path of the user's tty |
b3cbe40f EA |
397 | ** |
398 | ** Returns the pathname of the user's tty. Returns NULL if | |
399 | ** the user is not logged in or if s/he has write permission | |
400 | ** denied. | |
401 | ** | |
402 | ** Parameters: | |
403 | ** none | |
404 | ** | |
405 | ** Returns: | |
406 | ** pathname of the user's tty. | |
407 | ** NULL if not logged in or write permission denied. | |
408 | ** | |
409 | ** Side Effects: | |
410 | ** none. | |
411 | ** | |
412 | ** WARNING: | |
413 | ** Return value is in a local buffer. | |
414 | ** | |
b3cbe40f EA |
415 | ** Called By: |
416 | ** savemail | |
b3cbe40f EA |
417 | */ |
418 | ||
b3cbe40f EA |
419 | # include <sys/stat.h> |
420 | ||
421 | char * | |
422 | ttypath() | |
423 | { | |
424 | struct stat stbuf; | |
425 | register char *pathn; | |
b3cbe40f | 426 | extern char *ttyname(); |
29871fef | 427 | extern char *getlogin(); |
b3cbe40f EA |
428 | |
429 | /* compute the pathname of the controlling tty */ | |
7338e3d4 EA |
430 | if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && |
431 | (pathn = ttyname(0)) == NULL) | |
b3cbe40f EA |
432 | { |
433 | errno = 0; | |
434 | return (NULL); | |
435 | } | |
436 | ||
437 | /* see if we have write permission */ | |
a530c75f | 438 | if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode)) |
b3cbe40f EA |
439 | { |
440 | errno = 0; | |
441 | return (NULL); | |
442 | } | |
443 | ||
444 | /* see if the user is logged in */ | |
445 | if (getlogin() == NULL) | |
446 | return (NULL); | |
447 | ||
448 | /* looks good */ | |
449 | return (pathn); | |
450 | } | |
a530c75f EA |
451 | \f/* |
452 | ** CHECKCOMPAT -- check for From and To person compatible. | |
453 | ** | |
454 | ** This routine can be supplied on a per-installation basis | |
455 | ** to determine whether a person is allowed to send a message. | |
456 | ** This allows restriction of certain types of internet | |
457 | ** forwarding or registration of users. | |
458 | ** | |
459 | ** If the hosts are found to be incompatible, an error | |
460 | ** message should be given using "usrerr" and FALSE should | |
461 | ** be returned. | |
462 | ** | |
46b14b48 EA |
463 | ** 'NoReturn' can be set to suppress the return-to-sender |
464 | ** function; this should be done on huge messages. | |
465 | ** | |
a530c75f EA |
466 | ** Parameters: |
467 | ** to -- the person being sent to. | |
468 | ** | |
469 | ** Returns: | |
470 | ** TRUE -- ok to send. | |
471 | ** FALSE -- not ok. | |
472 | ** | |
473 | ** Side Effects: | |
474 | ** none (unless you include the usrerr stuff) | |
475 | */ | |
476 | ||
477 | bool | |
478 | checkcompat(to) | |
479 | register ADDRESS *to; | |
480 | { | |
22e6d6b8 EA |
481 | # ifdef lint |
482 | if (to == NULL) | |
483 | to++; | |
484 | # endif lint | |
97ad25b6 EA |
485 | # ifdef EXAMPLE_CODE |
486 | /* this code is intended as an example only */ | |
b14547d5 EA |
487 | register STAB *s; |
488 | ||
b14547d5 | 489 | s = stab("arpa", ST_MAILER, ST_FIND); |
7338e3d4 EA |
490 | if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer && |
491 | to->q_mailer == s->s_mailer) | |
b14547d5 EA |
492 | { |
493 | usrerr("No ARPA mail through this machine: see your system administration"); | |
97ad25b6 | 494 | /* NoReturn = TRUE; to supress return copy */ |
b14547d5 EA |
495 | return (FALSE); |
496 | } | |
97ad25b6 | 497 | # endif EXAMPLE_CODE |
a530c75f EA |
498 | return (TRUE); |
499 | } | |
7338e3d4 EA |
500 | \f/* |
501 | ** HOLDSIGS -- arrange to hold all signals | |
502 | ** | |
503 | ** Parameters: | |
504 | ** none. | |
505 | ** | |
506 | ** Returns: | |
507 | ** none. | |
508 | ** | |
509 | ** Side Effects: | |
510 | ** Arranges that signals are held. | |
511 | */ | |
512 | ||
513 | holdsigs() | |
514 | { | |
515 | } | |
516 | \f/* | |
517 | ** RLSESIGS -- arrange to release all signals | |
518 | ** | |
519 | ** This undoes the effect of holdsigs. | |
520 | ** | |
521 | ** Parameters: | |
522 | ** none. | |
523 | ** | |
524 | ** Returns: | |
525 | ** none. | |
526 | ** | |
527 | ** Side Effects: | |
528 | ** Arranges that signals are released. | |
529 | */ | |
530 | ||
531 | rlsesigs() | |
532 | { | |
533 | } | |
f7e74083 EA |
534 | \f/* |
535 | ** GETLA -- get the current load average | |
536 | ** | |
d209c154 EA |
537 | ** This code stolen from la.c. |
538 | ** | |
f7e74083 EA |
539 | ** Parameters: |
540 | ** none. | |
541 | ** | |
542 | ** Returns: | |
543 | ** The current load average as an integer. | |
544 | ** | |
545 | ** Side Effects: | |
546 | ** none. | |
547 | */ | |
548 | ||
549 | #ifdef VMUNIX | |
550 | ||
551 | #include <nlist.h> | |
552 | ||
553 | struct nlist Nl[] = | |
554 | { | |
555 | { "_avenrun" }, | |
556 | #define X_AVENRUN 0 | |
557 | { 0 }, | |
558 | }; | |
559 | ||
560 | getla() | |
561 | { | |
562 | static int kmem = -1; | |
2e3062fe EA |
563 | # ifdef sun |
564 | long avenrun[3]; | |
565 | # else | |
f7e74083 | 566 | double avenrun[3]; |
2e3062fe | 567 | # endif |
901911f8 | 568 | extern off_t lseek(); |
f7e74083 EA |
569 | |
570 | if (kmem < 0) | |
571 | { | |
fa483327 | 572 | kmem = open("/dev/kmem", 0, 0); |
f7e74083 EA |
573 | if (kmem < 0) |
574 | return (-1); | |
17a67c62 | 575 | (void) ioctl(kmem, (int) FIOCLEX, (char *) 0); |
f7e74083 EA |
576 | nlist("/vmunix", Nl); |
577 | if (Nl[0].n_type == 0) | |
578 | return (-1); | |
579 | } | |
fa483327 | 580 | if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 || |
17a67c62 | 581 | read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) |
fa42ff8e EA |
582 | { |
583 | /* thank you Ian */ | |
584 | return (-1); | |
585 | } | |
2e3062fe EA |
586 | # ifdef sun |
587 | return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); | |
588 | # else | |
f7e74083 | 589 | return ((int) (avenrun[0] + 0.5)); |
2e3062fe | 590 | # endif |
f7e74083 EA |
591 | } |
592 | ||
593 | #else VMUNIX | |
594 | ||
595 | getla() | |
596 | { | |
597 | return (0); | |
598 | } | |
599 | ||
600 | #endif VMUNIX | |
2e3062fe EA |
601 | \f/* |
602 | ** SHOULDQUEUE -- should this message be queued or sent? | |
603 | ** | |
604 | ** Compares the message cost to the load average to decide. | |
605 | ** | |
606 | ** Parameters: | |
607 | ** pri -- the priority of the message in question. | |
608 | ** | |
609 | ** Returns: | |
610 | ** TRUE -- if this message should be queued up for the | |
611 | ** time being. | |
612 | ** FALSE -- if the load is low enough to send this message. | |
613 | ** | |
614 | ** Side Effects: | |
615 | ** none. | |
616 | */ | |
617 | ||
618 | bool | |
619 | shouldqueue(pri) | |
620 | long pri; | |
621 | { | |
622 | int la; | |
623 | ||
624 | la = getla(); | |
625 | if (la < QueueLA) | |
626 | return (FALSE); | |
627 | return (pri > (QueueFactor / (la - QueueLA + 1))); | |
628 | } | |
629 | \f/* | |
630 | ** SETPROCTITLE -- set process title for ps | |
631 | ** | |
632 | ** Parameters: | |
633 | ** fmt -- a printf style format string. | |
634 | ** a, b, c -- possible parameters to fmt. | |
635 | ** | |
636 | ** Returns: | |
637 | ** none. | |
638 | ** | |
639 | ** Side Effects: | |
640 | ** Clobbers argv of our main procedure so ps(1) will | |
641 | ** display the title. | |
642 | */ | |
643 | ||
644 | /*VARARGS1*/ | |
645 | setproctitle(fmt, a, b, c) | |
646 | char *fmt; | |
647 | { | |
648 | # ifdef SETPROCTITLE | |
649 | register char *p; | |
f5ca8c6e | 650 | register int i; |
2e3062fe EA |
651 | extern char **Argv; |
652 | extern char *LastArgv; | |
f5ca8c6e | 653 | char buf[MAXLINE]; |
2e3062fe | 654 | |
f5ca8c6e | 655 | (void) sprintf(buf, fmt, a, b, c); |
2e3062fe EA |
656 | |
657 | /* make ps print "(sendmail)" */ | |
f5ca8c6e | 658 | p = Argv[0]; |
2e3062fe EA |
659 | *p++ = '-'; |
660 | ||
f5ca8c6e EA |
661 | i = strlen(buf); |
662 | if (i > LastArgv - p - 2) | |
663 | { | |
664 | i = LastArgv - p - 2; | |
665 | buf[i] = '\0'; | |
666 | } | |
667 | (void) strcpy(p, buf); | |
668 | p += i; | |
2e3062fe EA |
669 | while (p < LastArgv) |
670 | *p++ = ' '; | |
671 | # endif SETPROCTITLE | |
672 | } | |
8fd13041 EA |
673 | \f/* |
674 | ** REAPCHILD -- pick up the body of my child, lest it become a zombie | |
675 | ** | |
676 | ** Parameters: | |
677 | ** none. | |
678 | ** | |
679 | ** Returns: | |
680 | ** none. | |
681 | ** | |
682 | ** Side Effects: | |
683 | ** Picks up extant zombies. | |
684 | */ | |
685 | ||
686 | # ifdef VMUNIX | |
687 | # include <sys/wait.h> | |
688 | # endif VMUNIX | |
689 | ||
690 | reapchild() | |
691 | { | |
692 | # ifdef WNOHANG | |
693 | union wait status; | |
694 | ||
695 | while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0) | |
696 | continue; | |
697 | # else WNOHANG | |
698 | auto int status; | |
699 | ||
700 | while (wait(&status) > 0) | |
701 | continue; | |
702 | # endif WNOHANG | |
703 | } |