libpurple/protocols/zephyr/zephyr.c

changeset 40622
16bba33a970f
parent 40514
30d9cbf04922
child 40633
d884c4b6e202
equal deleted inserted replaced
40621:406ff566ad57 40622:16bba33a970f
88 int last_id; 88 int last_id;
89 unsigned short port; 89 unsigned short port;
90 char ourhost[HOST_NAME_MAX + 1]; 90 char ourhost[HOST_NAME_MAX + 1];
91 char ourhostcanon[HOST_NAME_MAX + 1]; 91 char ourhostcanon[HOST_NAME_MAX + 1];
92 zephyr_connection_type connection_type; 92 zephyr_connection_type connection_type;
93 int totzc[2];
94 int fromtzc[2];
95 char *exposure; 93 char *exposure;
96 pid_t tzc_pid; 94 GSubprocess *tzc_proc;
95 GOutputStream *tzc_stdin;
96 GInputStream *tzc_stdout;
97 gchar *away; 97 gchar *away;
98 }; 98 };
99 99
100 #define MAXCHILDREN 20 100 #define MAXCHILDREN 20
101 101
160 #ifdef WIN32 160 #ifdef WIN32
161 extern const char *username; 161 extern const char *username;
162 #endif 162 #endif
163 163
164 static Code_t zephyr_subscribe_to(zephyr_account* zephyr, char* class, char *instance, char *recipient, char* galaxy) { 164 static Code_t zephyr_subscribe_to(zephyr_account* zephyr, char* class, char *instance, char *recipient, char* galaxy) {
165 size_t result;
166 Code_t ret_val = -1; 165 Code_t ret_val = -1;
167 166
168 if (use_tzc(zephyr)) { 167 if (use_tzc(zephyr)) {
169 /* ((tzcfodder . subscribe) ("class" "instance" "recipient")) */ 168 /* ((tzcfodder . subscribe) ("class" "instance" "recipient")) */
170 gchar *zsubstr = g_strdup_printf("((tzcfodder . subscribe) (\"%s\" \"%s\" \"%s\"))\n",class,instance,recipient); 169 gchar *zsubstr;
171 size_t len = strlen(zsubstr); 170 GError *error = NULL;
172 result = write(zephyr->totzc[ZEPHYR_FD_WRITE],zsubstr,len); 171
173 if (result != len) { 172 zsubstr = g_strdup_printf(
174 purple_debug_error("zephyr", "Unable to write a message: %s\n", g_strerror(errno)); 173 "((tzcfodder . subscribe) (\"%s\" \"%s\" \"%s\"))\n", class,
174 instance, recipient);
175 if (!g_output_stream_write_all(zephyr->tzc_stdin, zsubstr,
176 strlen(zsubstr), NULL, NULL, &error)) {
177 purple_debug_error("zephyr", "Unable to write a message: %s",
178 error->message);
179 g_error_free(error);
175 } else { 180 } else {
176 ret_val = ZERR_NONE; 181 ret_val = ZERR_NONE;
177 } 182 }
178 g_free(zsubstr); 183 g_free(zsubstr);
179 } 184 }
1079 return ptree; 1084 return ptree;
1080 } 1085 }
1081 } 1086 }
1082 1087
1083 static parse_tree *read_from_tzc(zephyr_account* zephyr){ 1088 static parse_tree *read_from_tzc(zephyr_account* zephyr){
1084 struct timeval tv; 1089 GPollableInputStream *stream = G_POLLABLE_INPUT_STREAM(zephyr->tzc_stdout);
1085 fd_set rfds; 1090 gsize bufsize = 2048;
1086 int bufsize = 2048; 1091 gchar *buf = g_new(gchar, bufsize);
1087 char *buf = (char *)calloc(bufsize, 1); 1092 gchar *bufcur = buf;
1088 char *bufcur = buf; 1093 gboolean selected = FALSE;
1089 int selected = 0;
1090 parse_tree *incoming_msg; 1094 parse_tree *incoming_msg;
1091 1095
1092 FD_ZERO(&rfds); 1096 incoming_msg = NULL;
1093 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds); 1097
1094 tv.tv_sec = 0; 1098 while (TRUE) {
1095 tv.tv_usec = 0; 1099 GError *error = NULL;
1096 incoming_msg=NULL; 1100 if (g_pollable_input_stream_read_nonblocking(stream, bufcur, 1, NULL,
1097 1101 &error) < 0) {
1098 while (select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, &tv)) { 1102 if (error->code == G_IO_ERROR_WOULD_BLOCK) {
1099 selected = 1; 1103 g_error_free(error);
1100 if (read(zephyr->fromtzc[ZEPHYR_FD_READ], bufcur, 1) != 1) { 1104 break;
1101 purple_debug_error("zephyr", "couldn't read\n"); 1105 }
1106 purple_debug_error("zephyr", "couldn't read: %s", error->message);
1102 purple_connection_error(purple_account_get_connection(zephyr->account), PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "couldn't read"); 1107 purple_connection_error(purple_account_get_connection(zephyr->account), PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "couldn't read");
1103 free(buf); 1108 g_error_free(error);
1109 g_free(buf);
1104 return NULL; 1110 return NULL;
1105 } 1111 }
1112 selected = TRUE;
1106 bufcur++; 1113 bufcur++;
1107 if ((bufcur - buf) > (bufsize - 1)) { 1114 if ((bufcur - buf) > (bufsize - 1)) {
1108 if ((buf = realloc(buf, bufsize * 2)) == NULL) { 1115 if ((buf = g_realloc(buf, bufsize * 2)) == NULL) {
1109 purple_debug_error("zephyr","Ran out of memory\n"); 1116 purple_debug_error("zephyr","Ran out of memory\n");
1110 exit(-1); 1117 exit(-1);
1111 } else { 1118 } else {
1112 bufcur = buf + bufsize; 1119 bufcur = buf + bufsize;
1113 bufsize *= 2; 1120 bufsize *= 2;
1117 *bufcur = '\0'; 1124 *bufcur = '\0';
1118 1125
1119 if (selected) { 1126 if (selected) {
1120 incoming_msg = parse_buffer(buf,TRUE); 1127 incoming_msg = parse_buffer(buf,TRUE);
1121 } 1128 }
1122 free(buf); 1129 g_free(buf);
1123 return incoming_msg; 1130 return incoming_msg;
1124 } 1131 }
1125 1132
1126 static gint check_notify_tzc(gpointer data) 1133 static gint check_notify_tzc(gpointer data)
1127 { 1134 {
1337 /* doesn't matter if this fails or not; we'll just move on to the next one */ 1344 /* doesn't matter if this fails or not; we'll just move on to the next one */
1338 if (use_zeph02(zephyr)) { 1345 if (use_zeph02(zephyr)) {
1339 ZRequestLocations(chk, &ald, UNACKED, ZAUTH); 1346 ZRequestLocations(chk, &ald, UNACKED, ZAUTH);
1340 g_free(ald.user); 1347 g_free(ald.user);
1341 g_free(ald.version); 1348 g_free(ald.version);
1342 } else 1349 } else if (use_tzc(zephyr)) {
1343 if (use_tzc(zephyr)) { 1350 gchar *zlocstr;
1344 gchar *zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",chk); 1351 GError *error = NULL;
1345 size_t len = strlen(zlocstr); 1352
1346 size_t result = write(zephyr->totzc[ZEPHYR_FD_WRITE],zlocstr,len); 1353 zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n", chk);
1347 if (result != len) { 1354 if (!g_output_stream_write_all(zephyr->tzc_stdin, zlocstr,
1348 purple_debug_error("zephyr", "Unable to write a message: %s\n", g_strerror(errno)); 1355 strlen(zlocstr), NULL, NULL,
1349 } 1356 &error)) {
1350 g_free(zlocstr); 1357 purple_debug_error("zephyr", "Unable to write a message: %s",
1351 } 1358 error->message);
1359 g_error_free(error);
1360 }
1361 g_free(zlocstr);
1362 }
1352 } 1363 }
1353 1364
1354 return TRUE; 1365 return TRUE;
1355 } 1366 }
1356 1367
1552 return exp2; 1563 return exp2;
1553 } 1564 }
1554 return g_strdup(EXPOSE_REALMVIS); 1565 return g_strdup(EXPOSE_REALMVIS);
1555 } 1566 }
1556 1567
1568 static gssize
1569 pollable_input_stream_read_with_timeout(GPollableInputStream *stream,
1570 void *bufcur, gint64 timeout,
1571 GError **error)
1572 {
1573 gint64 now = g_get_monotonic_time();
1574
1575 while (g_get_monotonic_time() < now + timeout) {
1576 GError *local_error = NULL;
1577 gssize ret = g_pollable_input_stream_read_nonblocking(
1578 stream, bufcur, 1, NULL, &local_error);
1579 if (ret == 1) {
1580 return ret;
1581 } else {
1582 if (local_error->code == G_IO_ERROR_WOULD_BLOCK) {
1583 /* Keep on waiting if this is a blocking error. */
1584 g_clear_error(&local_error);
1585 } else {
1586 g_propagate_error(error, local_error);
1587 return ret;
1588 }
1589 }
1590 }
1591
1592 g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_TIMED_OUT,
1593 "tzc did not respond in time");
1594 return -1;
1595 }
1596
1557 static void zephyr_login(PurpleAccount * account) 1597 static void zephyr_login(PurpleAccount * account)
1558 { 1598 {
1559 PurpleConnection *gc; 1599 PurpleConnection *gc;
1560 zephyr_account *zephyr; 1600 zephyr_account *zephyr;
1561 gboolean read_anyone; 1601 gboolean read_anyone;
1590 zephyr->encoding = (char *)purple_account_get_string(purple_connection_get_account(gc), "encoding", ZEPHYR_FALLBACK_CHARSET); 1630 zephyr->encoding = (char *)purple_account_get_string(purple_connection_get_account(gc), "encoding", ZEPHYR_FALLBACK_CHARSET);
1591 purple_connection_update_progress(gc, _("Connecting"), 0, 8); 1631 purple_connection_update_progress(gc, _("Connecting"), 0, 8);
1592 1632
1593 /* XXX z_call_s should actually try to report the com_err determined error */ 1633 /* XXX z_call_s should actually try to report the com_err determined error */
1594 if (use_tzc(zephyr)) { 1634 if (use_tzc(zephyr)) {
1595 pid_t pid; 1635 gboolean found_ps = FALSE;
1596 /* purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "tzc not supported yet"); */ 1636 gchar **tzc_cmd_array = NULL;
1597 if ((pipe(zephyr->totzc) != 0) || (pipe(zephyr->fromtzc) != 0)) { 1637 GPollableInputStream *stream = NULL;
1598 purple_debug_error("zephyr", "pipe creation failed. killing\n"); 1638 gsize bufsize;
1599 exit(-1); 1639 gchar *buf = NULL;
1600 } 1640 gchar *bufcur = NULL;
1601 1641 gchar *ptr;
1602 pid = fork(); 1642 gint parenlevel = 0;
1603 1643 gchar *tempstr;
1604 if (pid == -1) { 1644 gint i;
1605 purple_debug_error("zephyr", "forking failed\n"); 1645 GError *error = NULL;
1606 exit(-1); 1646
1607 } 1647 /* tzc_command should really be of the form
1608 if (pid == 0) { 1648 path/to/tzc -e %s
1609 unsigned int i=0; 1649 or
1610 gboolean found_ps = FALSE; 1650 ssh username@hostname pathtotzc -e %s
1611 gchar ** tzc_cmd_array = g_strsplit(purple_account_get_string(purple_connection_get_account(gc),"tzc_command","/usr/bin/tzc -e %s")," ",0); 1651 -- this should not require a password, and ideally should be
1612 if (close(1) == -1) { 1652 kerberized ssh --
1613 exit(-1); 1653 or
1614 } 1654 fsh username@hostname pathtotzc -e %s
1615 if (dup2(zephyr->fromtzc[1], 1) == -1) { 1655 */
1616 exit(-1); 1656 if (!g_shell_parse_argv(purple_account_get_string(
1617 } 1657 purple_connection_get_account(gc),
1618 if (close(zephyr->fromtzc[1]) == -1) { 1658 "tzc_command", "/usr/bin/tzc -e %s"),
1619 exit(-1); 1659 NULL, &tzc_cmd_array, &error)) {
1620 } 1660 purple_debug_error("zephyr", "Unable to parse tzc_command: %s",
1621 if (close(0) == -1) { 1661 error->message);
1622 exit(-1); 1662 purple_connection_error(gc,
1623 } 1663 PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
1624 if (dup2(zephyr->totzc[0], 0) == -1) { 1664 "invalid tzc_command setting");
1625 exit(-1); 1665 g_error_free(error);
1626 } 1666 return;
1627 if (close(zephyr->totzc[0]) == -1) { 1667 }
1628 exit(-1); 1668 for (i = 0; tzc_cmd_array[i] != NULL; i++) {
1629 } 1669 if (g_str_equal(tzc_cmd_array[i], "%s")) {
1630 /* tzc_command should really be of the form 1670 g_free(tzc_cmd_array);
1631 path/to/tzc -e %s 1671 tzc_cmd_array[i] = g_strdup(zephyr->exposure);
1632 or 1672 found_ps = TRUE;
1633 ssh username@hostname pathtotzc -e %s 1673 }
1634 -- this should not require a password, and ideally should be kerberized ssh -- 1674 }
1635 or 1675
1636 fsh username@hostname pathtotzc -e %s 1676 if (!found_ps) {
1637 */ 1677 purple_debug_error("zephyr", "tzc exited early");
1638 while(tzc_cmd_array[i] != NULL){ 1678 purple_connection_error(
1639 if (!g_ascii_strncasecmp(tzc_cmd_array[i],"%s",2)) { 1679 gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1640 /* fprintf(stderr,"replacing %%s with %s\n",zephyr->exposure); */ 1680 "invalid output by tzc (or bad parsing code)");
1641 tzc_cmd_array[i] = g_strdup(zephyr->exposure); 1681 g_strfreev(tzc_cmd_array);
1642 found_ps = TRUE; 1682 return;
1643 1683 }
1684
1685 zephyr->tzc_proc = g_subprocess_newv(
1686 (const gchar *const *)tzc_cmd_array,
1687 G_SUBPROCESS_FLAGS_STDIN_PIPE | G_SUBPROCESS_FLAGS_STDOUT_PIPE,
1688 &error);
1689 g_strfreev(tzc_cmd_array);
1690 if (zephyr->tzc_proc == NULL) {
1691 purple_debug_error("zephyr", "tzc exited early: %s",
1692 error->message);
1693 purple_connection_error(
1694 gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1695 "invalid output by tzc (or bad parsing code)");
1696 g_error_free(error);
1697 return;
1698 }
1699 zephyr->tzc_stdin = g_subprocess_get_stdin_pipe(zephyr->tzc_proc);
1700 zephyr->tzc_stdout = g_subprocess_get_stdout_pipe(zephyr->tzc_proc);
1701
1702 stream = G_POLLABLE_INPUT_STREAM(zephyr->tzc_stdout);
1703 bufsize = 2048;
1704 buf = g_new(gchar, bufsize);
1705 bufcur = buf;
1706 parenlevel = 0;
1707
1708 purple_debug_info("zephyr", "about to read from tzc");
1709
1710 while (TRUE) {
1711 if (pollable_input_stream_read_with_timeout(
1712 stream, bufcur, 10 * G_USEC_PER_SEC, &error) < 0) {
1713 if (error->code == G_IO_ERROR_WOULD_BLOCK ||
1714 error->code == G_IO_ERROR_TIMED_OUT) {
1715 g_clear_error(&error);
1716 break;
1717 }
1718 purple_debug_error("zephyr", "couldn't read: %s",
1719 error->message);
1720 purple_connection_error(gc,
1721 PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1722 "couldn't read");
1723 g_error_free(error);
1724 g_free(buf);
1725 return;
1726 }
1727 bufcur++;
1728 if ((bufcur - buf) > (bufsize - 1)) {
1729 if ((buf = g_realloc(buf, bufsize * 2)) == NULL) {
1730 exit(-1);
1644 } else { 1731 } else {
1645 /* fprintf(stderr,"keeping %s\n",tzc_cmd_array[i]); */ 1732 bufcur = buf + bufsize;
1733 bufsize *= 2;
1646 } 1734 }
1647 i++; 1735 }
1648 } 1736 }
1649 1737 *bufcur = '\0';
1650 if (!found_ps) { 1738 ptr = buf;
1651 exit(-1); 1739
1652 } 1740 /* ignore all tzcoutput till we've received the first (*/
1653 1741 while (ptr < bufcur && (*ptr != '(')) {
1654 execvp(tzc_cmd_array[0], tzc_cmd_array); 1742 ptr++;
1655 exit(-1); 1743 }
1656 } 1744 if (ptr >= bufcur) {
1657 else { 1745 purple_connection_error(
1658 fd_set rfds; 1746 gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
1659 int bufsize = 2048; 1747 "invalid output by tzc (or bad parsing code)");
1660 char *buf = (char *)calloc(bufsize, 1); 1748 g_free(buf);
1661 char *bufcur = buf; 1749 return;
1662 struct timeval tv; 1750 }
1663 char *ptr; 1751
1664 int parenlevel=0; 1752 while (ptr < bufcur) {
1665 char* tempstr; 1753 if (*ptr == '(') {
1666 int tempstridx; 1754 parenlevel++;
1667 int select_status; 1755 } else if (*ptr == ')') {
1668 1756 parenlevel--;
1669 zephyr->tzc_pid = pid; 1757 }
1670 /* wait till we have data to read from ssh */ 1758 purple_debug_info("zephyr", "tzc parenlevel is %d", parenlevel);
1671 FD_ZERO(&rfds); 1759 switch (parenlevel) {
1672 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds);
1673
1674 tv.tv_sec = 10;
1675 tv.tv_usec = 0;
1676
1677 purple_debug_info("zephyr", "about to read from tzc\n");
1678
1679 if (waitpid(pid, NULL, WNOHANG) == 0) { /* Only select if tzc is still running */
1680 purple_debug_info("zephyr", "about to read from tzc\n");
1681 select_status = select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, NULL);
1682 }
1683 else {
1684 purple_debug_info("zephyr", "tzc exited early\n");
1685 select_status = -1;
1686 }
1687
1688 FD_ZERO(&rfds);
1689 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds);
1690 while (select_status > 0 &&
1691 select(zephyr->fromtzc[ZEPHYR_FD_READ] + 1, &rfds, NULL, NULL, &tv) > 0) {
1692 if (read(zephyr->fromtzc[ZEPHYR_FD_READ], bufcur, 1) != 1) {
1693 purple_debug_error("zephyr", "couldn't read\n");
1694 purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "couldn't read");
1695 free(buf);
1696 return;
1697 }
1698 bufcur++;
1699 if ((bufcur - buf) > (bufsize - 1)) {
1700 if ((buf = realloc(buf, bufsize * 2)) == NULL) {
1701 exit(-1);
1702 } else {
1703 bufcur = buf + bufsize;
1704 bufsize *= 2;
1705 }
1706 }
1707 FD_ZERO(&rfds);
1708 FD_SET(zephyr->fromtzc[ZEPHYR_FD_READ], &rfds);
1709 tv.tv_sec = 10;
1710 tv.tv_usec = 0;
1711
1712 }
1713 /* fprintf(stderr, "read from tzc\n"); */
1714 *bufcur = '\0';
1715 ptr = buf;
1716
1717 /* ignore all tzcoutput till we've received the first (*/
1718 while (ptr < bufcur && (*ptr !='(')) {
1719 ptr++;
1720 }
1721 if (ptr >=bufcur) {
1722 purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, "invalid output by tzc (or bad parsing code)");
1723 free(buf);
1724 return;
1725 }
1726
1727 while(ptr < bufcur) {
1728 if (*ptr == '(') {
1729 parenlevel++;
1730 }
1731 else if (*ptr == ')') {
1732 parenlevel--;
1733 }
1734 purple_debug_info("zephyr","tzc parenlevel is %d\n",parenlevel);
1735 switch (parenlevel) {
1736 case 0: 1760 case 0:
1737 break; 1761 break;
1738 case 1: 1762 case 1:
1739 /* Search for next beginning (, or for the ending */ 1763 /* Search for next beginning (, or for the ending */
1740 ptr++; 1764 ptr++;
1741 while((*ptr != '(') && (*ptr != ')') && (ptr <bufcur)) 1765 while ((*ptr != '(') && (*ptr != ')') && (ptr < bufcur)) {
1742 ptr++; 1766 ptr++;
1743 if (ptr >= bufcur) 1767 }
1744 purple_debug_error("zephyr","tzc parsing error\n"); 1768 if (ptr >= bufcur) {
1769 purple_debug_error("zephyr", "tzc parsing error");
1770 }
1745 break; 1771 break;
1746 case 2: 1772 case 2:
1747 /* You are probably at 1773 /* You are probably at
1748 (foo . bar ) or (foo . "bar") or (foo . chars) or (foo . numbers) or (foo . () ) 1774 (foo . bar ) or (foo . "bar") or (foo . chars) or (foo . numbers) or (foo . () )
1749 Parse all the data between the first and last f, and move past ) 1775 Parse all the data between the first and last f, and move past )
1750 */ 1776 */
1751 tempstr = g_malloc0(20000); 1777 tempstr = g_new0(gchar, 20000);
1752 tempstridx=0; 1778 i = 0;
1753 while(parenlevel >1) { 1779 while(parenlevel >1) {
1754 ptr++; 1780 ptr++;
1755 if (*ptr == '(') 1781 if (*ptr == '(')
1756 parenlevel++; 1782 parenlevel++;
1757 if (*ptr == ')') 1783 if (*ptr == ')')
1758 parenlevel--; 1784 parenlevel--;
1759 if (parenlevel > 1) { 1785 if (parenlevel > 1) {
1760 tempstr[tempstridx++]=*ptr; 1786 tempstr[i++] = *ptr;
1761 } else { 1787 } else {
1762 ptr++; 1788 ptr++;
1763 } 1789 }
1764 } 1790 }
1765 purple_debug_info("zephyr","tempstr parsed\n"); 1791 purple_debug_info("zephyr", "tempstr parsed");
1766 /* tempstr should now be a tempstridx length string containing all characters 1792 /* tempstr should now be a i-length string containing all
1767 from that after the first ( to the one before the last paren ). */ 1793 * characters from that after the first ( to the one before
1768 /* We should have the following possible lisp strings but we don't care 1794 * the last paren ). We should have the following possible
1769 (tzcspew . start) (version . "something") (pid . number)*/ 1795 * lisp strings but we don't care
1770 /* We care about 'zephyrid . "username@REALM.NAME"' and 'exposure . "SOMETHING"' */ 1796 * (tzcspew . start) (version . "something") (pid . number)
1771 tempstridx=0; 1797 * We care about 'zephyrid . "username@REALM.NAME"' and
1798 * 'exposure . "SOMETHING"' */
1799 i = 0;
1772 if (!g_ascii_strncasecmp(tempstr,"zephyrid",8)) { 1800 if (!g_ascii_strncasecmp(tempstr,"zephyrid",8)) {
1773 gchar* username = g_malloc0(100); 1801 gchar* username = g_malloc0(100);
1774 int username_idx=0; 1802 int username_idx=0;
1775 char *realm; 1803 char *realm;
1776 purple_debug_info("zephyr","zephyrid found\n"); 1804 purple_debug_info("zephyr", "zephyrid found");
1777 tempstridx+=8; 1805 i += 8;
1778 while(tempstr[tempstridx] !='"' && tempstridx < 20000) 1806 while (i < 20000 && tempstr[i] != '"') {
1779 tempstridx++; 1807 i++;
1780 tempstridx++; 1808 }
1781 while(tempstr[tempstridx] !='"' && tempstridx < 20000) 1809 i++;
1782 username[username_idx++]=tempstr[tempstridx++]; 1810 while (i < 20000 && tempstr[i] != '"') {
1811 username[username_idx++] = tempstr[i++];
1812 }
1783 1813
1784 zephyr->username = g_strdup_printf("%s",username); 1814 zephyr->username = g_strdup_printf("%s",username);
1785 if ((realm = strchr(username,'@'))) 1815 if ((realm = strchr(username,'@')))
1786 zephyr->realm = g_strdup_printf("%s",realm+1); 1816 zephyr->realm = g_strdup_printf("%s",realm+1);
1787 else { 1817 else {
1788 realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm",""); 1818 realm = (gchar *)purple_account_get_string(purple_connection_get_account(gc),"realm","");
1789 if (!*realm) { 1819 if (!*realm) {
1790 realm = "local-realm"; 1820 realm = "local-realm";
1791 } 1821 }
1792 zephyr->realm = g_strdup(realm); 1822 zephyr->realm = g_strdup(realm);
1793 g_strlcpy(__Zephyr_realm, (const char*)zephyr->realm, REALM_SZ-1); 1823 g_strlcpy(__Zephyr_realm,
1824 (const gchar *)zephyr->realm,
1825 REALM_SZ - 1);
1794 } 1826 }
1795 /* else { 1827 /* else {
1796 zephyr->realm = g_strdup("local-realm"); 1828 zephyr->realm = g_strdup("local-realm");
1797 }*/ 1829 }*/
1798 1830
1799 g_free(username); 1831 g_free(username);
1800 } else { 1832 } else {
1801 purple_debug_info("zephyr", "something that's not zephyr id found %s\n",tempstr); 1833 purple_debug_info(
1834 "zephyr",
1835 "something that's not zephyr id found %s",
1836 tempstr);
1802 } 1837 }
1803 1838
1804 /* We don't care about anything else yet */ 1839 /* We don't care about anything else yet */
1805 g_free(tempstr); 1840 g_free(tempstr);
1806 break; 1841 break;
1807 default: 1842 default:
1808 purple_debug_info("zephyr","parenlevel is not 1 or 2\n"); 1843 purple_debug_info("zephyr", "parenlevel is not 1 or 2");
1809 /* This shouldn't be happening */ 1844 /* This shouldn't be happening */
1810 break; 1845 break;
1811 } 1846 }
1812 if (parenlevel==0) 1847 if (parenlevel == 0) {
1813 break; 1848 break;
1814 } /* while (ptr < bufcur) */ 1849 }
1815 purple_debug_info("zephyr", "tzc startup done\n"); 1850 } /* while (ptr < bufcur) */
1816 free(buf); 1851 purple_debug_info("zephyr", "tzc startup done");
1817 } 1852 g_free(buf);
1818 } 1853 }
1819 else if ( use_zeph02(zephyr)) { 1854 else if ( use_zeph02(zephyr)) {
1820 gchar* realm; 1855 gchar* realm;
1821 z_call_s(ZInitialize(), "Couldn't initialize zephyr"); 1856 z_call_s(ZInitialize(), "Couldn't initialize zephyr");
1822 z_call_s(ZOpenPort(&(zephyr->port)), "Couldn't open port"); 1857 z_call_s(ZOpenPort(&(zephyr->port)), "Couldn't open port");
1966 } 2001 }
1967 2002
1968 static void zephyr_close(PurpleConnection * gc) 2003 static void zephyr_close(PurpleConnection * gc)
1969 { 2004 {
1970 zephyr_account *zephyr = purple_connection_get_protocol_data(gc); 2005 zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
1971 pid_t tzc_pid = zephyr->tzc_pid;
1972 2006
1973 g_list_free_full(zephyr->pending_zloc_names, g_free); 2007 g_list_free_full(zephyr->pending_zloc_names, g_free);
1974 2008
1975 if (purple_account_get_bool(purple_connection_get_account(gc), "write_anyone", FALSE)) 2009 if (purple_account_get_bool(purple_connection_get_account(gc), "write_anyone", FALSE))
1976 write_anyone(zephyr); 2010 write_anyone(zephyr);
1984 g_source_remove(zephyr->nottimer); 2018 g_source_remove(zephyr->nottimer);
1985 zephyr->nottimer = 0; 2019 zephyr->nottimer = 0;
1986 if (zephyr->loctimer) 2020 if (zephyr->loctimer)
1987 g_source_remove(zephyr->loctimer); 2021 g_source_remove(zephyr->loctimer);
1988 zephyr->loctimer = 0; 2022 zephyr->loctimer = 0;
1989 gc = NULL;
1990 if (use_zeph02(zephyr)) { 2023 if (use_zeph02(zephyr)) {
1991 z_call(ZCancelSubscriptions(0)); 2024 z_call(ZCancelSubscriptions(0));
1992 z_call(ZUnsetLocation()); 2025 z_call(ZUnsetLocation());
1993 z_call(ZClosePort()); 2026 z_call(ZClosePort());
1994 } else { 2027 } else {
1995 /* assume tzc */ 2028 /* assume tzc */
1996 if (kill(tzc_pid,SIGTERM) == -1) { 2029 #ifdef G_OS_UNIX
1997 int err=errno; 2030 GError *error = NULL;
1998 if (err==EINVAL) { 2031 g_subprocess_send_signal(zephyr->tzc_proc, SIGTERM);
1999 purple_debug_error("zephyr","An invalid signal was specified when killing tzc\n"); 2032 if (!g_subprocess_wait(zephyr->tzc_proc, NULL, &error)) {
2000 } 2033 purple_debug_error("zephyr",
2001 else if (err==ESRCH) { 2034 "error while attempting to close tzc: %s",
2002 purple_debug_error("zephyr","Tzc's pid didn't exist while killing tzc\n"); 2035 error->message);
2003 } 2036 g_error_free(error);
2004 else if (err==EPERM) { 2037 }
2005 purple_debug_error("zephyr","purple didn't have permission to kill tzc\n"); 2038 #else
2006 } 2039 g_subprocess_force_exit(zephyr->tzc_proc);
2007 else { 2040 #endif
2008 purple_debug_error("zephyr","miscellaneous error while attempting to close tzc\n"); 2041 zephyr->tzc_stdin = NULL;
2009 } 2042 zephyr->tzc_stdout = NULL;
2010 } 2043 g_clear_object(&zephyr->tzc_proc);
2011 } 2044 }
2012 } 2045 }
2013 2046
2014 static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instance, char* recipient, const char *im, 2047 static gboolean zephyr_send_message(zephyr_account *zephyr, gchar *zclass,
2015 const char *sig, char *opcode) ; 2048 gchar *instance, gchar *recipient,
2049 const gchar *im, const gchar *sig,
2050 gchar *opcode);
2016 2051
2017 static const char * zephyr_get_signature(void) 2052 static const char * zephyr_get_signature(void)
2018 { 2053 {
2019 /* XXX add zephyr error reporting */ 2054 /* XXX add zephyr error reporting */
2020 const char * sig =ZGetVariable("zwrite-signature"); 2055 const char * sig =ZGetVariable("zwrite-signature");
2128 } 2163 }
2129 2164
2130 return newmsg; 2165 return newmsg;
2131 } 2166 }
2132 2167
2133 static int zephyr_send_message(zephyr_account *zephyr,char* zclass, char* instance, char* recipient, const char *im, 2168 static gboolean
2134 const char *sig, char *opcode) 2169 zephyr_send_message(zephyr_account *zephyr, gchar *zclass, gchar *instance,
2170 gchar *recipient, const gchar *im, const gchar *sig,
2171 gchar *opcode)
2135 { 2172 {
2136 2173
2137 /* (From the tzc source) 2174 /* (From the tzc source)
2138 * emacs sends something of the form: 2175 * emacs sends something of the form:
2139 * ((class . "MESSAGE") 2176 * ((class . "MESSAGE")
2147 char *html_buf2; 2184 char *html_buf2;
2148 html_buf = html_to_zephyr(im); 2185 html_buf = html_to_zephyr(im);
2149 html_buf2 = purple_unescape_html(html_buf); 2186 html_buf2 = purple_unescape_html(html_buf);
2150 2187
2151 if(use_tzc(zephyr)) { 2188 if(use_tzc(zephyr)) {
2152 size_t len;
2153 size_t result;
2154 char* zsendstr; 2189 char* zsendstr;
2155 /* CMU cclub tzc doesn't grok opcodes for now */ 2190 /* CMU cclub tzc doesn't grok opcodes for now */
2156 char* tzc_sig = zephyr_tzc_escape_msg(sig); 2191 char* tzc_sig = zephyr_tzc_escape_msg(sig);
2157 char *tzc_body = zephyr_tzc_escape_msg(html_buf2); 2192 char *tzc_body = zephyr_tzc_escape_msg(html_buf2);
2158 zsendstr = g_strdup_printf("((tzcfodder . send) (class . \"%s\") (auth . t) (recipients (\"%s\" . \"%s\")) (message . (\"%s\" \"%s\")) ) \n", 2193 zsendstr = g_strdup_printf("((tzcfodder . send) (class . \"%s\") (auth . t) (recipients (\"%s\" . \"%s\")) (message . (\"%s\" \"%s\")) ) \n",
2159 zclass, instance, recipient, tzc_sig, tzc_body); 2194 zclass, instance, recipient, tzc_sig, tzc_body);
2160 /* fprintf(stderr,"zsendstr = %s\n",zsendstr); */ 2195 /* fprintf(stderr,"zsendstr = %s\n",zsendstr); */
2161 len = strlen(zsendstr); 2196
2162 result = write(zephyr->totzc[ZEPHYR_FD_WRITE], zsendstr, len); 2197 if (!g_output_stream_write_all(zephyr->tzc_stdin, zsendstr,
2163 if (result != len) { 2198 strlen(zsendstr), NULL, NULL, NULL)) {
2164 g_free(tzc_sig); 2199 g_free(tzc_sig);
2165 g_free(tzc_body); 2200 g_free(tzc_body);
2166 g_free(zsendstr); 2201 g_free(zsendstr);
2167 g_free(html_buf2); 2202 g_free(html_buf2);
2168 g_free(html_buf); 2203 g_free(html_buf);
2169 return errno; 2204 return FALSE;
2170 } 2205 }
2171 g_free(tzc_sig); 2206 g_free(tzc_sig);
2172 g_free(tzc_body); 2207 g_free(tzc_body);
2173 g_free(zsendstr); 2208 g_free(zsendstr);
2174 } else if (use_zeph02(zephyr)) { 2209 } else if (use_zeph02(zephyr)) {
2190 if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) { 2225 if (ZSendNotice(&notice, ZAUTH) != ZERR_NONE) {
2191 /* XXX handle errors here */ 2226 /* XXX handle errors here */
2192 g_free(buf); 2227 g_free(buf);
2193 g_free(html_buf2); 2228 g_free(html_buf2);
2194 g_free(html_buf); 2229 g_free(html_buf);
2195 return 0; 2230 return FALSE;
2196 } 2231 }
2197 purple_debug_info("zephyr","notice sent\n"); 2232 purple_debug_info("zephyr","notice sent\n");
2198 g_free(buf); 2233 g_free(buf);
2199 } 2234 }
2200 2235
2201 g_free(html_buf2); 2236 g_free(html_buf2);
2202 g_free(html_buf); 2237 g_free(html_buf);
2203 2238
2204 return 1; 2239 return TRUE;
2205 } 2240 }
2206 2241
2207 char *local_zephyr_normalize(zephyr_account *zephyr,const char *orig) 2242 char *local_zephyr_normalize(zephyr_account *zephyr,const char *orig)
2208 { 2243 {
2209 /* 2244 /*
2264 g_strdup(normalized_who)); 2299 g_strdup(normalized_who));
2265 } else { 2300 } else {
2266 /* XXX deal with errors somehow */ 2301 /* XXX deal with errors somehow */
2267 } 2302 }
2268 } else if (use_tzc(zephyr)) { 2303 } else if (use_tzc(zephyr)) {
2269 size_t len; 2304 GError *error = NULL;
2270 size_t result; 2305 gchar *zlocstr;
2271 char* zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",normalized_who); 2306
2272 zephyr->pending_zloc_names = g_list_append(zephyr->pending_zloc_names, g_strdup(normalized_who)); 2307 zephyr->pending_zloc_names = g_list_append(zephyr->pending_zloc_names, g_strdup(normalized_who));
2273 len = strlen(zlocstr); 2308 zlocstr = g_strdup_printf("((tzcfodder . zlocate) \"%s\")\n",
2274 result = write(zephyr->totzc[ZEPHYR_FD_WRITE],zlocstr,len); 2309 normalized_who);
2275 if (result != len) { 2310 if (!g_output_stream_write_all(zephyr->tzc_stdin, zlocstr,
2276 purple_debug_error("zephyr", "Unable to write a message: %s\n", g_strerror(errno)); 2311 strlen(zlocstr), NULL, NULL, &error)) {
2312 purple_debug_error("zephyr", "Unable to write a message: %s",
2313 error->message);
2314 g_error_free(error);
2277 } 2315 }
2278 g_free(zlocstr); 2316 g_free(zlocstr);
2279 } 2317 }
2280 } 2318 }
2281 2319
2282 static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) { 2320 static void zephyr_set_status(PurpleAccount *account, PurpleStatus *status) {
2283 size_t len;
2284 size_t result;
2285 PurpleConnection *gc = purple_account_get_connection(account); 2321 PurpleConnection *gc = purple_account_get_connection(account);
2286 zephyr_account *zephyr = purple_connection_get_protocol_data(gc); 2322 zephyr_account *zephyr = purple_connection_get_protocol_data(gc);
2287 PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status)); 2323 PurpleStatusPrimitive primitive = purple_status_type_get_primitive(purple_status_get_status_type(status));
2288 2324
2289 g_free(zephyr->away); 2325 g_free(zephyr->away);
2295 else if (primitive == PURPLE_STATUS_AVAILABLE) { 2331 else if (primitive == PURPLE_STATUS_AVAILABLE) {
2296 if (use_zeph02(zephyr)) { 2332 if (use_zeph02(zephyr)) {
2297 ZSetLocation(zephyr->exposure); 2333 ZSetLocation(zephyr->exposure);
2298 } 2334 }
2299 else { 2335 else {
2300 char *zexpstr = g_strdup_printf("((tzcfodder . set-location) (hostname . \"%s\") (exposure . \"%s\"))\n",zephyr->ourhost,zephyr->exposure); 2336 GError *error = NULL;
2301 len = strlen(zexpstr); 2337 gchar *zexpstr = g_strdup_printf("((tzcfodder . set-location)"
2302 result = write(zephyr->totzc[ZEPHYR_FD_WRITE],zexpstr,len); 2338 " (hostname . \"%s\")"
2303 if (result != len) { 2339 " (exposure . \"%s\"))\n",
2304 purple_debug_error("zephyr", "Unable to write message: %s\n", g_strerror(errno)); 2340 zephyr->ourhost, zephyr->exposure);
2341 if (g_output_stream_write_all(zephyr->tzc_stdin, zexpstr,
2342 strlen(zexpstr), NULL, NULL,
2343 &error)) {
2344 purple_debug_error("zephyr", "Unable to write message: %s",
2345 error->message);
2346 g_error_free(error);
2305 } 2347 }
2306 g_free(zexpstr); 2348 g_free(zexpstr);
2307 } 2349 }
2308 } 2350 }
2309 else if (primitive == PURPLE_STATUS_INVISIBLE) { 2351 else if (primitive == PURPLE_STATUS_INVISIBLE) {
2310 /* XXX handle errors */ 2352 /* XXX handle errors */
2311 if (use_zeph02(zephyr)) { 2353 if (use_zeph02(zephyr)) {
2312 ZSetLocation(EXPOSE_OPSTAFF); 2354 ZSetLocation(EXPOSE_OPSTAFF);
2313 } else { 2355 } else {
2314 char *zexpstr = g_strdup_printf("((tzcfodder . set-location) (hostname . \"%s\") (exposure . \"%s\"))\n",zephyr->ourhost,EXPOSE_OPSTAFF); 2356 GError *error = NULL;
2315 len = strlen(zexpstr); 2357 gchar *zexpstr = g_strdup_printf("((tzcfodder . set-location)"
2316 result = write(zephyr->totzc[ZEPHYR_FD_WRITE],zexpstr,len); 2358 " (hostname . \"%s\")"
2317 if (result != len) { 2359 " (exposure . \"%s\"))\n",
2318 purple_debug_error("zephyr", "Unable to write message: %s\n", g_strerror(errno)); 2360 zephyr->ourhost, EXPOSE_OPSTAFF);
2361 if (g_output_stream_write_all(zephyr->tzc_stdin, zexpstr,
2362 strlen(zexpstr), NULL, NULL,
2363 &error)) {
2364 purple_debug_error("zephyr", "Unable to write message: %s",
2365 error->message);
2366 g_error_free(error);
2319 } 2367 }
2320 g_free(zexpstr); 2368 g_free(zexpstr);
2321 } 2369 }
2322 } 2370 }
2323 } 2371 }

mercurial