zabetia@tiger.UUCP (04/07/87)
Before you complain about macput, here it is. Along with a couple other goodies. #! /bin/sh # This archive created: Mon Apr 6 17:41:23 1987 # by Mahboud Zabetian (Princeton U., EE) on # This is a shell archive, meaning: # 1. Remove everything above the #! /bin/sh line. # 2. Save the resulting text in a file. # 3. Execute the file with /bin/sh (not csh) to create: # macbin.c # macget.c # macput.c export PATH; PATH=/bin:/usr/bin:$PATH echo shar: "extracting 'macbin.c'" '(3976 characters)' if test -f 'macbin.c' then echo shar: "will not over-write existing file 'macbin.c'" else cat << \SHAR_EOF > 'macbin.c' /*--------------------------------------------------------------------* | Version : 2.0 | | Author : Jim Budler | | Copyright Oct 13, 1986 | | Placed in public domain Oct 14, 1986 | | Enjoy | *--------------------------------------------------------------------*/ #include <stdio.h> #include <errno.h> extern int errno; main(argc,argv) int argc; char **argv; { /* structure of the info file - from MacBin.C char zero1; char nlen; char name[63]; char type[4]; 65 0101 char creator[4]; 69 char flags; 73 char zero2; 74 0112 char location[6]; 80 char protected; 81 0121 char zero3; 82 0122 char dflen[4]; char rflen[4]; char cdate[4]; char mdate[4]; */ FILE *fd, *ofd; char bname[128]; char iname[128]; char dname[128]; char rname[128]; char oname[128]; char buf[128]; char * charp, * cmd; char * rindex(); int verbose = 0; if ((cmd = rindex(argv[0], '/')) != NULL) ++cmd; else cmd = argv[0]; if (argc > 1) if (!strcmp(argv[1], "-v")) { verbose = 1; --argc; ++argv; } if (argc < 2) { fprintf(stderr,"Usage:\n\t%s [-v] filename(s)\n",cmd); exit(EINVAL); } while ( argc > 1 ) { (void) bzero(buf,128); if (( charp = rindex (argv[1], '.')) == NULL) strcpy(bname, argv[1]); else { *charp = '\0'; if ( strcmp(++charp,"data") && strcmp (charp, "info") && strcmp (charp, "rsrc")) { *(--charp) = '.'; /* put it back */ strcpy(bname, argv[1]); } else { strcpy(bname,argv[1]); --argc; ++argv; } } strcpy(oname,bname); strcat(oname,".bin"); strcpy(iname,bname); strcat(iname,".info"); strcpy(dname,bname); strcat(dname,".data"); strcpy(rname,bname); strcat(rname,".rsrc"); if (verbose) fprintf (stderr, "Converting %s\n", bname); while ( argc > 1 && (!strcmp(argv[1], iname) || !strcmp(argv[1], dname) || !strcmp(argv[1], rname))) { --argc; ++argv; } if ((ofd = fopen( oname, "w")) == NULL){ perror(oname); --argc; ++argv; continue; } if ((fd = fopen(iname,"r")) == NULL){ if ( verbose ) fprintf ( stderr, "No %s\n", iname); fclose(ofd); unlink(oname); --argc; ++argv; continue; } if (fread(buf, sizeof(*buf), 128, fd) > 0){ if (buf[74] & 0x40) buf[81] = '\1'; /* protected */ buf[74] = '\0'; /* clear zero2 */ fwrite(buf, sizeof(*buf),128, ofd); (void) bzero(buf,128); } fclose(fd); if ((fd = fopen(dname,"r")) == NULL){ if ( verbose ) fprintf ( stderr, "No %s\n", dname); fclose(ofd); unlink(oname); --argc; ++argv; continue; } while (fread(buf, sizeof(*buf),128, fd) > 0){ fwrite(buf, sizeof(*buf),128, ofd); (void) bzero(buf,128); } fclose(fd); if ((fd = fopen(rname,"r")) == NULL){ if ( verbose ) fprintf ( stderr, "No %s\n", rname); fclose(ofd); unlink(oname); --argc; ++argv; continue; } while (fread(buf, sizeof(*buf),128, fd) > 0){ fwrite(buf, sizeof(*buf),128, ofd); (void) bzero(buf,128); } fclose(fd); fclose(ofd); } } #ifdef BZERO /* File : bzero.c Author : Richard A. O'Keefe. Updated: 23 April 1984 Defines: bzero() bzero(dst, len) moves "len" 0 bytes to "dst". Thus to clear a disc buffer to 0s do bzero(buffer, BUFSIZ). Note: the "b" routines are there to exploit certain VAX order codes, but the MOVC5 instruction will only move 65535 characters. The asm code is presented for your interest and amusement. */ #include "strings.h" #if VaxAsm void bzero(dst, len) char *dst; int len; { asm("movc5 $0,*4(ap),$0,8(ap),*4(ap)"); } #else ~VaxAsm void bzero(dst, len) register char *dst; register int len; { while (--len >= 0) *dst++ = 0; } #endif VaxAsm #endif /* BZERO */ SHAR_EOF if test 3976 -ne "`wc -c < 'macbin.c'`" then echo shar: "error transmitting 'macbin.c'" '(should have been 3976 characters)' fi fi echo shar: "extracting 'macget.c'" '(7646 characters)' if test -f 'macget.c' then echo shar: "will not over-write existing file 'macget.c'" else cat << \SHAR_EOF > 'macget.c' #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <sgtty.h> #ifdef NO_RENAME #define rename(old, new) link(old, new); unlink(old) #endif /* Mac time of 00:00:00 GMT, Jan 1, 1970 */ #define TIMEDIFF 0x7c25b080 #define RECORDBYTES 132 #define DATABYTES 128 #define NAMEBYTES 63 #define RETRIES 10 #define SOHTIMO 10 #define LINTIMO 20 #define CHRTIMO 2 #define MAXRECNO 0xff #define BYTEMASK 0xff #define TMO -1 #define DUP '\000' #define SOH '\001' #define EOT '\004' #define ACK '\006' #define NAK '\025' #define CAN '\030' #define EEF '\032' #define ESC '\033' #define H_NLENOFF 1 #define H_NAMEOFF 2 /* 65 <-> 80 is the FInfo structure */ #define H_TYPEOFF 65 #define H_AUTHOFF 69 #define H_LOCKOFF 81 #define H_DLENOFF 83 #define H_RLENOFF 87 #define H_CTIMOFF 91 #define H_MTIMOFF 95 #define H_OLD_DLENOFF 81 #define H_OLD_RLENOFF 85 #define TEXT 0 #define DATA 1 #define RSRC 2 #define FULL 3 int mode, txtmode; int pre_beta; /* -o flag; for compatibility with MacTerminal Version -0.15X */ struct macheader { char m_name[NAMEBYTES+1]; char m_type[4]; char m_author[4]; long m_datalen; long m_rsrclen; long m_createtime; long m_modifytime; } mh; struct filenames { char f_info[256]; char f_data[256]; char f_rsrc[256]; } files; char tmpname[16]; int lastack; char buf[DATABYTES]; /* * macget -- receive file from macintosh using xmodem protocol * Dave Johnson, Brown University Computer Science * * (c) 1984 Brown University * may be used but not sold without permission * * created ddj 5/22/84 * revised ddj 6/29/84 -- added [-rdu] options * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout() * revised ddj 11/7/84 -- renamed send_sync() -> get_sync() */ char usage[] = "usage: \"macget [-o] [-rdu] [filename]\"\n"; main(ac, av) char **av; { char *name; mode = FULL; name = ""; ac--; av++; while (ac) { if (av[0][0] == '-') { switch (av[0][1]) { case 'r': mode = RSRC; break; case 'd': mode = DATA; break; case 'u': mode = TEXT; break; case 'o': pre_beta++; break; default: fprintf(stderr, usage); exit(1); } } else { name = av[0]; } ac--; av++; } setup_tty(); if (get_sync() == ACK) { txtmode = 0; recv_hdr(name); if (mode == TEXT) txtmode++; recv_file(files.f_data, mh.m_datalen, 1); txtmode = 0; recv_file(files.f_rsrc, mh.m_rsrclen, 0); } reset_tty(); } recv_hdr(name) char *name; { long get4(); int n; FILE *fp; char *np; strcpy(tmpname, "#machdrXXXXXX"); mktemp(tmpname); recv_file(tmpname, (long)DATABYTES, 1); fp = fopen(tmpname, "r"); if (fp == NULL) { perror("temp file"); cleanup(-1); } fread(buf, 1, DATABYTES, fp); fclose(fp); if (name && *name) { n = strlen(name); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, name, n); mh.m_name[n] = '\0'; } else { n = buf[H_NLENOFF] & BYTEMASK; if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, buf + H_NAMEOFF, n); mh.m_name[n] = '\0'; } for (np = mh.m_name; *np; np++) if (*np == ' ') *np = '_'; if (mode == FULL) { sprintf(files.f_info, "%s.info", mh.m_name); rename(tmpname, files.f_info); tmpname[0] = '\0'; sprintf(files.f_data, "%s.data", mh.m_name); sprintf(files.f_rsrc, "%s.rsrc", mh.m_name); } else { unlink(tmpname); tmpname[0] = '\0'; switch (mode) { case RSRC: sprintf(files.f_data, "/dev/null"); sprintf(files.f_rsrc, "%s.rsrc", mh.m_name); break; case DATA: sprintf(files.f_data, "%s.data", mh.m_name); sprintf(files.f_rsrc, "/dev/null"); break; case TEXT: sprintf(files.f_data, "%s.text", mh.m_name); sprintf(files.f_rsrc, "/dev/null"); break; } } strncpy(mh.m_type, buf + H_TYPEOFF, 4); strncpy(mh.m_author, buf + H_AUTHOFF, 4); if (pre_beta) { mh.m_datalen = get4(buf + H_OLD_DLENOFF); mh.m_rsrclen = get4(buf + H_OLD_RLENOFF); } else { mh.m_datalen = get4(buf + H_DLENOFF); mh.m_rsrclen = get4(buf + H_RLENOFF); mh.m_createtime = get4(buf + H_CTIMOFF); mh.m_modifytime = get4(buf + H_MTIMOFF); } } recv_file(fname, bytes, more) char *fname; long bytes; int more; { register int status, n; FILE *outf; int naks = 0; lastack = 0; outf = fopen(fname, "w"); if (outf == NULL) { perror(fname); cleanup(-1); } for (;;) { status = rec_read(buf, DATABYTES); switch (status) { case EOT: if (!pre_beta) tputc(ACK); if (more) tputc(NAK); fclose(outf); return; case ACK: tputc(ACK); naks = 0; n = (bytes > DATABYTES) ? DATABYTES : bytes; bytes -= n; fwrite(buf, n, 1, outf); break; case DUP: tputc(ACK); naks = 0; break; case NAK: purge(CHRTIMO); if (naks++ < RETRIES) { tputc(NAK); break; } /* fall through */ case CAN: tputc(CAN); fclose(outf); /* unlink fname? */ cleanup(-1); /* NOTREACHED */ } } } get_sync() { int c; for (;;) { c = tgetc(60); switch (c) { case ESC: break; case CAN: case EOT: case TMO: return c; default: continue; } c = tgetc(1); if (c != 'a') continue; tputc(ACK); return ACK; } } rec_read(buf, recsize) char buf[]; int recsize; { int c, rec, rec_bar, cksum; c = tgetc(SOHTIMO); switch (c) { case TMO: default: return NAK; case EOT: return EOT; case CAN: return CAN; case SOH: /* read header */ rec = tgetc(CHRTIMO); if (rec == TMO) return NAK; rec_bar = tgetc(CHRTIMO); if (rec_bar == TMO) return NAK; /* check header */ if (rec != MAXRECNO - rec_bar) return NAK; /* fill buffer */ cksum = tgetrec(buf, recsize, LINTIMO); if (cksum == TMO) return NAK; /* get checksum */ c = tgetc(CHRTIMO); if (c == TMO) return NAK; if (c != (cksum & BYTEMASK)) return NAK; /* check record number */ if (rec == lastack) return DUP; if (rec != ((lastack + 1) & MAXRECNO)) return CAN; else { lastack = rec; return ACK; } } /* NOTREACHED */ } purge(timeout) int timeout; { int c; do { c = tgetc(timeout); } while (c != TMO); } static int ttyfd; static FILE *ttyf; jmp_buf timobuf; tgetrec(buf, count, timeout) char *buf; int count, timeout; { char *bp; int i, cksum; if (setjmp(timobuf)) return TMO; alarm(timeout); i = fread(buf, 1, count, ttyf); alarm(0); if (i != count) return TMO; cksum = 0; bp = buf; for (i = 0; i < count; bp++, i++) { cksum += *bp; if (txtmode && *bp == '\r') *bp = '\n'; } return cksum; } tgetc(timeout) int timeout; { int c; if (setjmp(timobuf)) return TMO; alarm(timeout); c = getc(ttyf); alarm(0); if (c == -1) /* probably hung up or logged off */ return EOT; else return c & BYTEMASK; } tputc(c) char c; { write(ttyfd, &c, 1); } timedout() { signal(SIGALRM, timedout); /* for pre-4.2 systems */ longjmp(timobuf, 1); } static struct sgttyb otty, ntty; /* should turn messages off */ setup_tty() { int cleanup(); int timedout(); ttyf = stdin; ttyfd = fileno(stdout); ioctl(ttyfd, TIOCGETP, &otty); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGQUIT, cleanup); signal(SIGTERM, cleanup); signal(SIGALRM, timedout); ntty = otty; ntty.sg_flags = RAW|ANYP; ioctl(ttyfd, TIOCSETP, &ntty); } reset_tty() { sleep(2); /* should wait for output to drain */ ioctl(ttyfd, TIOCSETP, &otty); } cleanup(sig) int sig; { if (tmpname[0] != '\0') unlink(tmpname); reset_tty(); exit(sig); } long get4(bp) char *bp; { register int i; long value = 0; for (i = 0; i < 4; i++) { value <<= 8; value |= (*bp & BYTEMASK); bp++; } return value; } SHAR_EOF if test 7646 -ne "`wc -c < 'macget.c'`" then echo shar: "error transmitting 'macget.c'" '(should have been 7646 characters)' fi fi echo shar: "extracting 'macput.c'" '(8100 characters)' if test -f 'macput.c' then echo shar: "will not over-write existing file 'macput.c'" else cat << \SHAR_EOF > 'macput.c' #include <stdio.h> #include <signal.h> #include <setjmp.h> #include <sgtty.h> #include <time.h> #include <sys/types.h> #include <sys/stat.h> #include <sys/timeb.h> /* Mac time of 00:00:00 GMT, Jan 1, 1970 */ #define TIMEDIFF 0x7c25b080 #define RECORDBYTES 132 #define DATABYTES 128 #define NAMEBYTES 63 #define RETRIES 10 #define ACKTIMO 10 #define MAXRECNO 0xff #define BYTEMASK 0xff #define TMO -1 #define DUP '\000' #define SOH '\001' #define EOT '\004' #define ACK '\006' #define NAK '\025' #define CAN '\030' #define EEF '\032' #define ESC '\033' #define H_NLENOFF 1 #define H_NAMEOFF 2 /* 65 <-> 80 is the FInfo structure */ #define H_TYPEOFF 65 #define H_AUTHOFF 69 #define H_LOCKOFF 81 #define H_DLENOFF 83 #define H_RLENOFF 87 #define H_CTIMOFF 91 #define H_MTIMOFF 95 #define H_OLD_DLENOFF 81 #define H_OLD_RLENOFF 85 #define TEXT 0 #define DATA 1 #define RSRC 2 #define FULL 3 int mode, txtmode; int pre_beta; /* -o flag; for compatibility with MacTerminal Version -0.15X */ struct macheader { char m_name[NAMEBYTES+1]; char m_type[4]; char m_author[4]; long m_datalen; long m_rsrclen; long m_createtime; long m_modifytime; } mh; struct filenames { char f_info[256]; char f_data[256]; char f_rsrc[256]; } files; int recno; char buf[DATABYTES]; /* * macput -- send file to macintosh using xmodem protocol * Dave Johnson, Brown University Computer Science * * (c) 1984 Brown University * may be used but not sold without permission * * created ddj 6/17/84 * revised ddj 7/16/84 -- protocol changes for MacTerminal Beta Version 0.5X * revised ddj 7/31/84 -- pre-4.2 signal bugs fixed in timedout() * revised ddj 7/31/84 -- fixed timeout problem in initial handshake */ char usage[] = "usage: \"macput [-o] [-rdu] [-t type] [-a author] [-n name] filename\"\n"; main(ac, av) char **av; { int n; char *filename; if (ac == 1) { fprintf(stderr, usage); exit(1); } mode = FULL; ac--; av++; while (ac) { if (av[0][0] == '-') { switch (av[0][1]) { case 'r': mode = RSRC; strncpy(mh.m_type, "APPL", 4); strncpy(mh.m_author, "CCOM", 4); break; case 'u': mode = TEXT; strncpy(mh.m_type, "TEXT", 4); strncpy(mh.m_author, "MACA", 4); break; case 'd': mode = DATA; strncpy(mh.m_type, "TEXT", 4); strncpy(mh.m_author, "????", 4); break; case 'n': if (ac > 1) { ac--; av++; n = strlen(av[0]); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, av[0], n); mh.m_name[n] = '\0'; break; } else goto bad_usage; case 't': if (ac > 1) { ac--; av++; strncpy(mh.m_type, av[0], 4); break; } else goto bad_usage; case 'a': if (ac > 1) { ac--; av++; strncpy(mh.m_author, av[0], 4); break; } else goto bad_usage; case 'o': pre_beta++; break; default: bad_usage: fprintf(stderr, usage); exit(1); } } else { filename = av[0]; } ac--; av++; } setup_tty(); find_files(filename, mode); if (mode != FULL) forge_info(); if (send_sync() == ACK) { txtmode = 0; sleep(1); /* added to make sure info block is recieved */ send_file(files.f_info, 1); if (mode != FULL) unlink(files.f_info); if (mode == TEXT) txtmode++; send_file(files.f_data, 1); txtmode = 0; send_file(files.f_rsrc, 0); } reset_tty(); } find_files(filename, mode) char *filename; { int n, tdiff; struct tm *tp; struct timeb tbuf; struct stat stbuf; sprintf(files.f_data, "%s.data", filename); sprintf(files.f_rsrc, "%s.rsrc", filename); if (mode == FULL) { sprintf(files.f_info, "%s.info", filename); if (stat(files.f_info, &stbuf) != 0) { perror(files.f_info); cleanup(-1); } return; } else { strcpy(files.f_info, "#machdrXXXXXX"); mktemp(files.f_info); } if (mode == RSRC) { strcpy(files.f_data, "/dev/null"); if (stat(files.f_rsrc, &stbuf) != 0) { strcpy(files.f_rsrc, filename); if (stat(files.f_rsrc, &stbuf) != 0) { perror(files.f_rsrc); cleanup(-1); } } mh.m_datalen = 0; mh.m_rsrclen = stbuf.st_size; } else { strcpy(files.f_rsrc, "/dev/null"); if (stat(files.f_data, &stbuf) != 0) { sprintf(files.f_data, "%s.text", filename); if (stat(files.f_data, &stbuf) != 0) { strcpy(files.f_data, filename); if (stat(files.f_data, &stbuf) != 0) { perror(files.f_data); cleanup(-1); } } } mh.m_datalen = stbuf.st_size; mh.m_rsrclen = 0; } if (!pre_beta) { ftime(&tbuf); tp = localtime(&tbuf.time); tdiff = TIMEDIFF - tbuf.timezone * 60; if (tp->tm_isdst) tdiff += 60 * 60; mh.m_createtime = stbuf.st_mtime + tdiff; mh.m_modifytime = stbuf.st_mtime + tdiff; } if (mh.m_name[0] == '\0') { n = strlen(filename); if (n > NAMEBYTES) n = NAMEBYTES; strncpy(mh.m_name, filename, n); mh.m_name[n] = '\0'; } } forge_info() { int n; char *np; FILE *fp; for (np = mh.m_name; *np; np++) if (*np == '_') *np = ' '; buf[H_NLENOFF] = n = np - mh.m_name; strncpy(buf + H_NAMEOFF, mh.m_name, n); strncpy(buf + H_TYPEOFF, mh.m_type, 4); strncpy(buf + H_AUTHOFF, mh.m_author, 4); if (pre_beta) { put4(buf + H_OLD_DLENOFF, mh.m_datalen); put4(buf + H_OLD_RLENOFF, mh.m_rsrclen); } else { put4(buf + H_DLENOFF, mh.m_datalen); put4(buf + H_RLENOFF, mh.m_rsrclen); put4(buf + H_CTIMOFF, mh.m_createtime); put4(buf + H_MTIMOFF, mh.m_modifytime); } fp = fopen(files.f_info, "w"); if (fp == NULL) { perror("temp file"); cleanup(-1); } fwrite(buf, 1, DATABYTES, fp); fclose(fp); } send_sync() { int c, i; for (i = 0; i < 3; i++) { tputc(ESC); tputc('a'); while ((c = tgetc(ACKTIMO)) != TMO) { switch (c) { case CAN: case EOT: case ACK: return c; default: continue; } } fprintf(stderr, "starting handshake timeout\r\n"); } fprintf(stderr, "giving up\r\n"); return CAN; } send_file(fname, more) char *fname; int more; { register int status, i, n; FILE *inf; inf = fopen(fname, "r"); if (inf == NULL) { perror(fname); cleanup(-1); } recno = 1; for (;;) { n = fread(buf, 1, DATABYTES, inf); if (n > 0) { for (i = 0; i < RETRIES; i++) { send_rec(buf, DATABYTES); status = tgetc(ACKTIMO); if (status != NAK) break; } if (status == NAK || status == CAN) { fclose(inf); cleanup(-1); /* NOTREACHED */ } } if (n < DATABYTES) { tputc(EOT); if (!pre_beta) { status = tgetc(ACKTIMO); } if (more) { status = tgetc(ACKTIMO); } return; } recno++; recno &= MAXRECNO; } } send_rec(buf, recsize) char buf[]; int recsize; { int i, cksum; char *bp; cksum = 0; bp = buf; for (i = 0; i < recsize; i++, bp++) { if (txtmode && *bp == '\n') *bp = '\r'; cksum += *bp; } tputc(SOH); tputc((char)recno); tputc((char)(MAXRECNO - recno)); tputrec(buf, recsize); tputc((char)cksum); } static int ttyfd; static FILE *ttyf; static jmp_buf timobuf; tgetc(timeout) int timeout; { int c; if (setjmp(timobuf)) return TMO; alarm(timeout); c = getc(ttyf); alarm(0); if (c == -1) /* probably hung up or logged off */ return EOT; else return c & BYTEMASK; } tputrec(buf, count) char *buf; int count; { write(ttyfd, buf, count); } tputc(c) char c; { write(ttyfd, &c, 1); } timedout() { signal(SIGALRM, timedout); /* for pre-4.2 systems */ longjmp(timobuf, 1); } static struct sgttyb otty, ntty; /* should turn messages off */ setup_tty() { int cleanup(); int timedout(); ttyf = stdin; ttyfd = fileno(stdin); ioctl(ttyfd, TIOCGETP, &otty); signal(SIGHUP, cleanup); signal(SIGINT, cleanup); signal(SIGQUIT, cleanup); signal(SIGTERM, cleanup); signal(SIGALRM, timedout); ntty = otty; ntty.sg_flags = RAW|ANYP; ioctl(ttyfd, TIOCSETP, &ntty); } reset_tty() { if (ttyf != NULL) { sleep(2); /* should wait for output to drain */ ioctl(ttyfd, TIOCSETP, &otty); } } cleanup(sig) int sig; { reset_tty(); exit(sig); } put4(bp, value) char *bp; long value; { register int i, c; for (i = 0; i < 4; i++) { c = (value >> 24) & BYTEMASK; value <<= 8; *bp++ = c; } } SHAR_EOF if test 8100 -ne "`wc -c < 'macput.c'`" then echo shar: "error transmitting 'macput.c'" '(should have been 8100 characters)' fi fi exit 0 # End of shell archive -- Mahboud Zabetian allegra! --\ zabetia@tiger.princeton.edu 232 Pyne Hall mhuxi! -----\ (609) 452-2285 Princeton University seismo! -----\ (609) 734-0246 Princeton, NJ 08544 attunix! ------ princeton!zabetia