|
|
1.1 root 1: /*
2: * Rec'd from Lauren Weinstein, 7-16-84.
3: * Send a one-line message to
4: * another user or a number of users.
5: * This is setuid in order to
6: * use execute permission on the
7: * terminal to allow/disallow msgs.
8: *
9: * The super user may use the "-s" flag to suppress the user id
10: * prefix on messages, which also suppresses any error messages,
11: * and forces an exit code of 0 unless an error condition occurs.
12: * This is mainly for use by other programs (e.g. "rmail").
13: */
14:
15: #include <stdio.h>
16: #include <utmp.h>
17: #include <sys/stat.h>
18: #include <signal.h>
19:
20: #define MAXMSG 256 /* Longest message allowable */
21: #define NUSER 100 /* Maximum number of users to send to */
22: #define ALARMT 10 /* Message send timeout in seconds */
23:
24: char msgbuf[MAXMSG];
25: struct users {
26: char *u_name;
27: int u_flag;
28: } users[NUSER];
29:
30: int wtimeout; /* non-zero for timeout on tty write */
31: int suppress; /* non-zero to suppress id headers, etc. */
32:
33: char usemsg[] = "\
34: Usage: msg user\n\
35: msg user ... message\n\
36: ";
37:
38: char *getlogin();
39: char *ttyname();
40: int catch();
41:
42: main(argc, argv)
43: char *argv[];
44: {
45: char *fromuname;
46: register int i;
47: register struct users *ulp = users;
48:
49:
50: /* are we the superuser and was the "-s" flag given? */
51: if (!geteuid() && argc > 1 && !strcmp(argv[1], "-s"))
52: { suppress++; /* set "suppress user id" prefix flag */
53: close(2); /* close error output */
54: open("/dev/null", 1); /* reopen fd 2 on /dev/null */
55: argc--; /* adjust args */
56: argv++;
57: }
58:
59: if (argc < 2)
60: usage();
61: if ((fromuname = getlogin()) == NULL)
62: fromuname = "daemon";
63: if (argc==2 || strcmp(argv[argc-1], "-")==0)
64: fgets(msgbuf, MAXMSG, stdin);
65: else {
66: strcpy(msgbuf, argv[argc-1]);
67: strcat(msgbuf, "\r\n");
68: }
69: if (argc == 2)
70: (ulp++)->u_name = argv[1];
71: else
72: for (i=1; i<argc-1; i++)
73: (ulp++)->u_name = argv[i];
74: exit(msg(suppress ? 0 : fromuname));
75: }
76:
77: /*
78: * Find out terminal names for the
79: * given user-list and complain about
80: * those not logged in.
81: */
82: msg(f)
83: char *f;
84: {
85: register struct users *up;
86: register FILE *fp;
87: register int st = 0;
88: static struct utmp ut;
89:
90: if ((fp = fopen("/etc/utmp", "r")) == NULL) {
91: fprintf(stderr, "msg: /etc/utmp not accessible\n");
92: exit(2);
93: }
94: while (fread(&ut, sizeof ut, 1, fp) == 1) {
95: if (ut.ut_name[0] == '\0')
96: continue;
97: for (up = users; up->u_name != NULL; up++)
98: if (strncmp(ut.ut_name, up->u_name, DIRSIZ) == 0)
99: break;
100: if (up->u_name == NULL)
101: continue;
102: send(f, &ut);
103: up->u_flag = 1;
104: }
105: for (up = users; up->u_name != NULL; up++)
106: if (up->u_flag == 0) {
107: fprintf(stderr, "%s: not logged in\n", up->u_name);
108: if (!suppress)
109: st = 1; /* indicate user not logged in */
110: }
111: return(st);
112: }
113:
114: /*
115: * Send the message. Return non-zero if
116: * it does not work or is not allowed.
117: */
118: send(f, up)
119: char *f;
120: register struct utmp *up;
121: {
122: FILE *tf;
123: register struct stat sb;
124: char tty[40], c;
125: register char abortf = 0;
126:
127: sprintf(tty, "/dev/%.*s", sizeof up->ut_line, up->ut_line);
128: if ((tf = fopen(tty, "w")) == NULL) {
129: fprintf(stderr, "msg: cannot open %.*s\n",
130: sizeof up->ut_line, up->ut_line);
131: return;
132: }
133: if (fstat(fileno(tf), &sb) < 0)
134: { fprintf(stderr, "msg: can't send to %.*s\n",
135: sizeof up->ut_name, up->ut_name);
136: fclose(tf);
137: return;
138: }
139: if ((sb.st_mode&S_IEXEC) == 0) {
140: if (!getuid()) /* is our real uid su? */
141: { fprintf(stderr,
142: "User \"%.*s\" is denying messages. Override? ",
143: sizeof up->ut_name, up->ut_name);
144: if ((c = getchar()) != 'y')
145: abortf++; /* flag abort */
146: while (c != EOF && c != '\n') /* flush remaining input */
147: c = getchar();
148: if (abortf) /* don't want override? */
149: { fclose(tf);
150: return;
151: }
152: }
153: else
154: { fprintf(stderr, "write: no permission to write to %.*s\n",
155: sizeof up->ut_name, up->ut_name);
156: fclose(tf);
157: return;
158: }
159: }
160: signal(SIGALRM, &catch); /* catch alarms */
161: alarm(ALARMT); /* set timeout */
162: if (f == NULL)
163: fprintf(tf, "\r\n\007%s", msgbuf); /* send the msg */
164: else
165: fprintf(tf, "\r\n\007%s: %s", f, msgbuf);
166: alarm(0); /* turn off timeout */
167: if (wtimeout) /* timeout on write? */
168: { wtimeout = 0; /* clear timeout flag */
169: fprintf(stderr, "msg: can't send to %.*s\n",
170: sizeof up->ut_name, up->ut_name);
171: }
172: fclose(tf);
173: }
174:
175: /* for alarm timeout */
176: catch()
177: {
178: wtimeout++; /* set write timeout flag */
179: }
180:
181: usage()
182: {
183: fprintf(stderr, usemsg);
184: exit(2);
185: }
186:
187:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.