root/lang/c/cmd2twitter/cmd2twitter.c

Revision 1940, 10.6 kB (checked in by mootoh, 4 years ago)

r2881@yebisu: moto | 2007-11-23 16:03:35 +0900
cmd2twitter - send command lines to Twitter.

Line 
1/* -*- Mode: C; indent-tabs-mode: nil;
2   c-basic-offset: 8 c-style: "K&R" -*- */
3/*
4 * Copyright (c) 1980 Regents of the University of California.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. All advertising materials mentioning features or use of this software
16 *    must display the following acknowledgement:
17 *      This product includes software developed by the University of
18 *      California, Berkeley and its contributors.
19 * 4. Neither the name of the University nor the names of its contributors
20 *    may be used to endorse or promote products derived from this software
21 *    without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 * SUCH DAMAGE.
34 */
35
36/* 1999-02-22 Arkadiusz Mi��kiewicz <misiek@misiek.eu.org>
37 * - added Native Language Support
38 */
39
40/* 2002-04-17 Satoru Takabayashi <satoru@namazu.org>
41 * - modify `script' to create `chatty'.
42 */
43
44/* 2007-11-23 Motohiro Takayama <mootoh@gmail.com>
45 * - modify `chatty' to create `cmd2twitter'.
46 */
47
48/*
49 * script
50 */
51#include <sys/types.h>
52#include <sys/stat.h>
53#include <termios.h>
54#include <sys/ioctl.h>
55#include <sys/time.h>
56#include <sys/file.h>
57#include <sys/signal.h>
58#include <stdio.h>
59
60#if defined(SVR4)
61#include <stdlib.h>
62#include <unistd.h>
63#include <fcntl.h>
64#include <stropts.h>
65#endif /* SVR4 */
66
67#ifdef __linux__
68#include <unistd.h>
69#include <string.h>
70#else
71#ifdef __APPLE__
72#include <unistd.h>
73#include <string.h>
74#endif
75#endif
76
77#include <sys/time.h>
78
79#define HAVE_inet_aton
80#define HAVE_scsi_h
81#define HAVE_kd_h
82
83#define _(FOO) FOO
84
85#ifdef HAVE_openpty
86#include <libutil.h>
87#endif
88
89#include <errno.h>
90
91#if defined(SVR4) && !defined(CDEL)
92#if defined(_POSIX_VDISABLE)
93#define CDEL _POSIX_VDISABLE
94#elif defined(CDISABLE)
95#define CDEL CDISABLE
96#else /* not _POSIX_VISIBLE && not CDISABLE */
97#define CDEL 255
98#endif /* not _POSIX_VISIBLE && not CDISABLE */
99#endif /* SVR4 && ! CDEL */
100
101void done(void);
102void fail(void);
103void fixtty(void);
104void getmaster(void);
105void getslave(void);
106void doinput(const char*);
107void dooutput(void);
108void doshell(const char*);
109
110char    *shell;
111int     master;
112int     slave;
113int     child;
114int     subchild;
115char    *fname;
116
117char user[BUFSIZ];
118char pass[BUFSIZ];
119char post[BUFSIZ];
120
121struct  termios tt;
122struct  winsize win;
123int     lb;
124int     l;
125#if !defined(SVR4)
126#ifndef HAVE_openpty
127char    line[] = "/dev/ptyXX";
128#endif
129#endif /* !SVR4 */
130
131
132#include <stdlib.h>
133typedef struct {
134  char str[BUFSIZ];
135  char *top;
136  char *tail;
137} RevBuf;
138
139RevBuf* revbuf_new              (void);
140void    revbuf_add              (RevBuf *revbuf, int ch);
141void    revbuf_clear            (RevBuf *revbuf);
142char*   revbuf_top              (RevBuf *revbuf);
143int     revbuf_full_p           (RevBuf *revbuf);
144void    watch_input             (RevBuf *revbuf,
145    const char *str, int len);
146
147  int
148main(argc, argv)
149  int argc;
150  char *argv[];
151{
152  extern int optind;
153  int ch;
154  void finish();
155  char *getenv();
156  char *command = NULL;
157  char *usage = "usage: cmd2twitter <username> <password>\n";
158
159  while ((ch = getopt(argc, argv, "h?")) != EOF)
160    switch((char)ch) {
161      case 'h':
162      case '?':
163      default:
164        fprintf(stderr, _(usage));
165        exit(1);
166    }
167  argc -= optind;
168  argv += optind;
169
170  if (argc != 2) {
171    fprintf(stderr, _(usage));
172    exit(1);
173  }
174
175  shell = getenv("SHELL");
176  if (shell == NULL)
177    shell = "/bin/sh";
178
179  getmaster();
180  fixtty();
181
182  (void) signal(SIGCHLD, finish);
183  child = fork();
184  if (child < 0) {
185    perror("fork");
186    fail();
187  }
188  if (child == 0) {
189    subchild = child = fork();
190    if (child < 0) {
191      perror("fork");
192      fail();
193    }
194    if (child)
195      dooutput();
196    else
197      doshell(command);
198  }
199
200  strncpy(user, argv[0], BUFSIZ);
201  strncpy(pass, argv[1], BUFSIZ);
202
203  doinput(argv[0]);
204
205  return 0;
206}
207
208  char *
209reverse (char *str)
210{
211  int i, len = strlen(str);
212
213  str = strdup(str);
214  for (i = 0; i < len / 2; i++) {
215    char w = str[i];
216    str[i] = str[len - i - 1];
217    str[len - i - 1] = w;
218  }
219  return str;
220}
221
222  RevBuf *
223revbuf_new (void)
224{
225  RevBuf *revbuf = malloc(sizeof(RevBuf));
226  if (revbuf == NULL)
227    abort();
228  revbuf->tail = revbuf->str + BUFSIZ - 1;
229  *(revbuf->tail) = '\0';
230  revbuf->top = revbuf->tail;
231  return revbuf;
232}
233
234  void
235revbuf_add (RevBuf *revbuf, int ch)
236{
237  revbuf->top--;
238  *(revbuf->top) = ch;
239}
240
241  int
242revbuf_full_p (RevBuf *revbuf)
243{
244  return revbuf->top == revbuf->str;
245}
246
247  char *
248revbuf_top (RevBuf *revbuf)
249{
250  return revbuf->top;
251}
252
253  void
254revbuf_clear (RevBuf *revbuf)
255{
256  revbuf->top = revbuf->tail;
257}
258
259void reverse_to_dst(char *dst, const char *src) {
260  int i;
261  int len = strlen(src)-1;
262  for (i=0; i<len; i++) {
263    dst[i] = src[len-i];
264  }
265}
266
267  void
268watch_input (RevBuf *revbuf, const char *str, int len)
269{
270  int i;
271
272  for (i = 0; i < len; i++) {
273    int  ch = str[i];
274    if (revbuf_full_p(revbuf))
275      revbuf_clear(revbuf);
276    revbuf_add(revbuf, ch);
277
278    if (ch == '\n' || ch == '\r') {
279      char status[BUFSIZ];
280      memset(status, 0, BUFSIZ);
281      memset(post, 0, BUFSIZ);
282      reverse_to_dst(status, revbuf_top(revbuf));
283      snprintf(post, BUFSIZ, "curl -s "
284        "--basic --user \"%s:%s\" --data-ascii "
285        "\"status=%s\" "
286        "\"http://twitter.com/statuses/update.json\"",
287        user, pass, status);
288      system(post);
289
290      revbuf_clear(revbuf);
291    }
292  }
293}
294
295  void
296doinput(const char *file_name)
297{
298  register int cc;
299  char ibuf[BUFSIZ];
300
301  RevBuf*       revbuf = revbuf_new();
302
303  setbuf(stdout, NULL);
304#ifdef HAVE_openpty
305  (void) close(slave);
306#endif
307
308  while ((cc = read(0, ibuf, BUFSIZ)) > 0) {
309    watch_input(revbuf, ibuf, cc);
310    (void) write(master, ibuf, cc);
311  }
312  done();
313}
314
315#include <sys/wait.h>
316
317  void
318finish()
319{
320#if defined(SVR4)
321  int status;
322#else /* !SVR4 */
323  union wait status;
324#endif /* !SVR4 */
325  register int pid;
326  register int die = 0;
327
328  while ((pid = wait3((int *)&status, WNOHANG, 0)) > 0)
329    if (pid == child)
330      die = 1;
331
332  if (die)
333    done();
334}
335
336  void
337dooutput()
338{
339  int cc;
340  time_t tvec, time();
341  char obuf[BUFSIZ], *ctime();
342
343  setbuf(stdout, NULL);
344  (void) close(0);
345#ifdef HAVE_openpty
346  (void) close(slave);
347#endif
348  tvec = time((time_t *)NULL);
349  for (;;) {
350    cc = read(master, obuf, BUFSIZ);
351    if (cc <= 0)
352      break;
353    (void) write(1, obuf, cc);
354  }
355
356  done();
357}
358
359  void
360doshell(const char* command)
361{
362  /***
363    int t;
364
365    t = open(_PATH_TTY, O_RDWR);
366    if (t >= 0) {
367    (void) ioctl(t, TIOCNOTTY, (char *)0);
368    (void) close(t);
369    }
370   ***/
371  getslave();
372  (void) close(master);
373  (void) dup2(slave, 0);
374  (void) dup2(slave, 1);
375  (void) dup2(slave, 2);
376  (void) close(slave);
377
378  if (!command) {
379    execl(shell, strrchr(shell, '/') + 1, "-i", 0);
380  } else {
381    execl(shell, strrchr(shell, '/') + 1, "-c", command, 0);   
382  }
383  perror(shell);
384  fail();
385}
386
387  void
388fixtty()
389{
390  struct termios rtt;
391
392  rtt = tt;
393#if defined(SVR4)
394  rtt.c_iflag = 0;
395  rtt.c_lflag &= ~(ISIG|ICANON|XCASE|ECHO|ECHOE|ECHOK|ECHONL);
396  rtt.c_oflag = OPOST;
397  rtt.c_cc[VINTR] = CDEL;
398  rtt.c_cc[VQUIT] = CDEL;
399  rtt.c_cc[VERASE] = CDEL;
400  rtt.c_cc[VKILL] = CDEL;
401  rtt.c_cc[VEOF] = 1;
402  rtt.c_cc[VEOL] = 0;
403#else /* !SVR4 */
404  cfmakeraw(&rtt);
405  rtt.c_lflag &= ~ECHO;
406#endif /* !SVR4 */
407  (void) tcsetattr(0, TCSAFLUSH, &rtt);
408}
409
410  void
411fail()
412{
413  (void) kill(0, SIGTERM);
414  done();
415}
416
417  void
418done()
419{
420  time_t tvec, time();
421  char *ctime();
422
423  if (subchild) {
424    tvec = time((time_t *)NULL);
425    (void) close(master);
426  } else {
427    (void) tcsetattr(0, TCSAFLUSH, &tt);
428  }
429  exit(0);
430}
431
432  void
433getmaster()
434{
435#if defined(SVR4)
436  (void) tcgetattr(0, &tt);
437  (void) ioctl(0, TIOCGWINSZ, (char *)&win);
438  if ((master = open("/dev/ptmx", O_RDWR)) < 0) {
439    perror("open(\"/dev/ptmx\", O_RDWR)");
440    fail();
441  }
442#else /* !SVR4 */
443#ifdef HAVE_openpty
444  (void) tcgetattr(0, &tt);
445  (void) ioctl(0, TIOCGWINSZ, (char *)&win);
446  if (openpty(&master, &slave, NULL, &tt, &win) < 0) {
447    fprintf(stderr, _("openpty failed\n"));
448    fail();
449  }
450#else
451  char *pty, *bank, *cp;
452  struct stat stb;
453
454  pty = &line[strlen("/dev/ptyp")];
455  for (bank = "pqrs"; *bank; bank++) {
456    line[strlen("/dev/pty")] = *bank;
457    *pty = '0';
458    if (stat(line, &stb) < 0)
459      break;
460    for (cp = "0123456789abcdef"; *cp; cp++) {
461      *pty = *cp;
462      master = open(line, O_RDWR);
463      if (master >= 0) {
464        char *tp = &line[strlen("/dev/")];
465        int ok;
466
467        /* verify slave side is usable */
468        *tp = 't';
469        ok = access(line, R_OK|W_OK) == 0;
470        *tp = 'p';
471        if (ok) {
472          (void) tcgetattr(0, &tt);
473          (void) ioctl(0, TIOCGWINSZ,
474              (char *)&win);
475          return;
476        }
477        (void) close(master);
478      }
479    }
480  }
481  fprintf(stderr, _("Out of pty's\n"));
482  fail();
483#endif /* not HAVE_openpty */
484#endif /* !SVR4 */
485}
486
487  void
488getslave()
489{
490#if defined(SVR4)
491  (void) setsid();
492  grantpt( master);
493  unlockpt(master);
494  if ((slave = open((const char *)ptsname(master), O_RDWR)) < 0) {
495    perror("open(fd, O_RDWR)");
496    fail();
497  }
498  if (isastream(slave)) {
499    if (ioctl(slave, I_PUSH, "ptem") < 0) {
500      perror("ioctl(fd, I_PUSH, ptem)");
501      fail();
502    }
503    if (ioctl(slave, I_PUSH, "ldterm") < 0) {
504      perror("ioctl(fd, I_PUSH, ldterm)");
505      fail();
506    }
507#ifndef _HPUX_SOURCE
508    if (ioctl(slave, I_PUSH, "ttcompat") < 0) {
509      perror("ioctl(fd, I_PUSH, ttcompat)");
510      fail();
511    }
512#endif
513    (void) ioctl(0, TIOCGWINSZ, (char *)&win);
514  }
515#else /* !SVR4 */
516#ifndef HAVE_openpty
517  line[strlen("/dev/")] = 't';
518  slave = open(line, O_RDWR);
519  if (slave < 0) {
520    perror(line);
521    fail();
522  }
523  (void) tcsetattr(slave, TCSAFLUSH, &tt);
524  (void) ioctl(slave, TIOCSWINSZ, (char *)&win);
525#endif
526  (void) setsid();
527  (void) ioctl(slave, TIOCSCTTY, 0);
528#endif /* SVR4 */
529}
Note: See TracBrowser for help on using the browser.