telco.c 26 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564
  1. /*
  2. * This file is part of the UCB release of Plan 9. It is subject to the license
  3. * terms in the LICENSE file found in the top-level directory of this
  4. * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
  5. * part of the UCB release of Plan 9, including this file, may be copied,
  6. * modified, propagated, or distributed except according to the terms contained
  7. * in the LICENSE file.
  8. */
  9. #include <u.h>
  10. #include <libc.h>
  11. #include <auth.h>
  12. #include <fcall.h>
  13. #define LOGFILE "telco"
  14. /*
  15. * Rather than reading /adm/users, which is a lot of work for
  16. * a toy progdev, we assume all groups have the form
  17. * NNN:user:user:
  18. * meaning that each user is the leader of his own group.
  19. */
  20. enum
  21. {
  22. OPERM = 0x3, /* mask of all permission types in open mode */
  23. Ndev = 8,
  24. Nreq = (Ndev*3)/2,
  25. Nrbuf = 32*1024,
  26. };
  27. typedef struct Fid Fid;
  28. typedef struct Dev Dev;
  29. typedef struct Request Request;
  30. typedef struct Type Type;
  31. struct Fid
  32. {
  33. Qid qid;
  34. int16_t busy;
  35. int16_t open;
  36. int fid;
  37. Fid *next;
  38. char *user;
  39. };
  40. struct Request
  41. {
  42. Request *next;
  43. Fid *fid;
  44. uint32_t tag;
  45. int count;
  46. int flushed;
  47. };
  48. struct Dev
  49. {
  50. Lock;
  51. /* device state */
  52. int ctl; /* control fd */
  53. int data; /* data fd */
  54. char *path; /* to device */
  55. Type *t;
  56. Type *baset;
  57. int speed;
  58. int fclass;
  59. /* fs emulation */
  60. int open;
  61. long perm;
  62. char *name;
  63. char *user;
  64. char msgbuf[128];
  65. Request *r;
  66. Request *rlast;
  67. /* input reader */
  68. int monitoring; /* monitor pid */
  69. char rbuf[Nrbuf];
  70. char *rp;
  71. char *wp;
  72. long pid;
  73. };
  74. enum
  75. {
  76. Devmask= (Ndev-1)<<8,
  77. Qlvl1= 0,
  78. Qlvl2= 1,
  79. Qclone= 2,
  80. Qlvl3= 3,
  81. Qdata= 4,
  82. Qctl= 5,
  83. Pexec = 1,
  84. Pwrite = 2,
  85. Pread = 4,
  86. Pother = 1,
  87. Pgroup = 8,
  88. Powner = 64,
  89. };
  90. char *names[] =
  91. {
  92. [Qlvl1] "/",
  93. [Qlvl2] "telco",
  94. [Qclone] "clone",
  95. [Qlvl3] "",
  96. [Qdata] "data",
  97. [Qctl] "ctl",
  98. };
  99. #define DEV(q) ((((uint32_t)(q).path)&Devmask)>>8)
  100. #define TYPE(q) (((uint32_t)(q).path)&((1<<8)-1))
  101. #define MKQID(t, i) ((((i)<<8)&Devmask) | (t))
  102. enum
  103. {
  104. /*
  105. * modem specific commands
  106. */
  107. Cerrorcorrection = 0, /* error correction */
  108. Ccompression, /* compression */
  109. Cflowctl, /* CTS/RTS */
  110. Crateadjust, /* follow line speed */
  111. Cfclass2, /* set up for fax */
  112. Cfclass0, /* set up for data */
  113. Ncommand,
  114. };
  115. struct Type
  116. {
  117. char *name;
  118. char *ident; /* inquire request */
  119. char *response; /* inquire response (strstr) */
  120. char *basetype; /* name of base type */
  121. char *commands[Ncommand];
  122. };
  123. /*
  124. * Fax setup summary
  125. *
  126. * FCLASS=2 - set to service class 2, i.e., one where the fax handles timing
  127. * FTBC=0 - ???
  128. * FREL=1 - ???
  129. * FCQ=1 - receive copy quality checking enabled
  130. * FBOR=1 - set reversed bit order for phase C data
  131. * FCR=1 - the DCE can receive message data, bit 10 in the DIS or
  132. * DTC frame will be set
  133. * FDIS=,3 - limit com speed to 9600 baud
  134. */
  135. Type typetab[] =
  136. {
  137. { "Rockwell", 0, 0, 0,
  138. "AT\\N7", /* auto reliable (V.42, fall back to MNP, to none) */
  139. "AT%C1\\J0", /* negotiate for compression, don't change port baud rate */
  140. "AT\\Q3", /* CTS/RTS flow control */
  141. "AT\\J1",
  142. "AT+FCLASS=2\rAT+FCR=1\r",
  143. "AT+FCLASS=0",
  144. },
  145. { "ATT2400", "ATI9", "E2400", "Rockwell",
  146. "AT\\N3", /* auto reliable (MNP, fall back to none) */
  147. 0,
  148. 0,
  149. 0,
  150. 0,
  151. 0,
  152. },
  153. { "ATT14400", "ATI9", "E14400", "Rockwell",
  154. 0,
  155. 0,
  156. 0,
  157. 0,
  158. 0,
  159. 0,
  160. },
  161. { "MT1432", "ATI2", "MT1432", 0,
  162. "AT&E1", /* auto reliable (V.42, fall back to none) */
  163. "AT&E15$BA0", /* negotiate for compression */
  164. "AT&E4", /* CTS/RTS flow control */
  165. "AT$BA1", /* don't change port baud rate */
  166. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1\rAT+FDIS=,3",
  167. "AT+FCLASS=0",
  168. },
  169. { "MT2834", "ATI2", "MT2834", "MT1432",
  170. 0,
  171. 0,
  172. 0,
  173. 0,
  174. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1",
  175. 0,
  176. },
  177. { "VOCAL", "ATI6", "144DPL+FAX", "Rockwell",
  178. "AT\\N3", /* auto reliable (V.42, fall back to MNP, fall back to none) */
  179. "AT%C3\\J0", /* negotiate for compression, don't change port baud rate */
  180. 0,
  181. 0,
  182. "AT+FCLASS=2\rAT+FTBC=0\rAT+FREL=1\rAT+FCQ=1\rAT+FBOR=1\rAT+FCR=1",
  183. "AT+FCLASS=0",
  184. },
  185. { 0, },
  186. };
  187. /*
  188. * modem return codes
  189. */
  190. enum
  191. {
  192. Ok,
  193. Success,
  194. Failure,
  195. Noise,
  196. Found,
  197. };
  198. /*
  199. * modem return messages
  200. */
  201. typedef struct Msg Msg;
  202. struct Msg
  203. {
  204. char *text;
  205. int type;
  206. };
  207. Msg msgs[] =
  208. {
  209. { "OK", Ok, },
  210. { "NO CARRIER", Failure, },
  211. { "ERROR", Failure, },
  212. { "NO DIALTONE", Failure, },
  213. { "BUSY", Failure, },
  214. { "NO ANSWER", Failure, },
  215. { "CONNECT", Success, },
  216. { 0, 0 },
  217. };
  218. Fid *fids;
  219. Dev *dev;
  220. int ndev;
  221. int mfd[2];
  222. char *user;
  223. uint8_t mdata[8192+IOHDRSZ];
  224. int messagesize = sizeof mdata;
  225. Fcall thdr;
  226. Fcall rhdr;
  227. char errbuf[ERRMAX];
  228. uint8_t statbuf[STATMAX];
  229. int pulsed;
  230. int verbose;
  231. int maxspeed = 56000;
  232. char *srcid = "plan9";
  233. int answer = 1;
  234. Fid *newfid(int);
  235. int devstat(Dir*, uint8_t*, int);
  236. int devgen(Qid, int, Dir*, uint8_t*, int);
  237. void error(char*);
  238. void io(void);
  239. void *erealloc(void*, uint32_t);
  240. void *emalloc(uint32_t);
  241. void usage(void);
  242. int perm(Fid*, Dev*, int);
  243. void setspeed(Dev*, int);
  244. int getspeed(char*, int);
  245. char *dialout(Dev*, char*);
  246. void onhook(Dev*);
  247. int readmsg(Dev*, int, char*);
  248. void monitor(Dev*);
  249. int getinput(Dev*, char*, int);
  250. void serve(Dev*);
  251. void receiver(Dev*);
  252. char* modemtype(Dev*, int, int);
  253. char *rflush(Fid*), *rversion(Fid*),
  254. *rattach(Fid*), *rauth(Fid*), *rwalk(Fid*),
  255. *ropen(Fid*), *rcreate(Fid*),
  256. *rread(Fid*), *rwrite(Fid*), *rclunk(Fid*),
  257. *rremove(Fid*), *rstat(Fid*), *rwstat(Fid*);
  258. char *(*fcalls[])(Fid*) = {
  259. [Tflush] rflush,
  260. [Tversion] rversion,
  261. [Tattach] rattach,
  262. [Tauth] rauth,
  263. [Twalk] rwalk,
  264. [Topen] ropen,
  265. [Tcreate] rcreate,
  266. [Tread] rread,
  267. [Twrite] rwrite,
  268. [Tclunk] rclunk,
  269. [Tremove] rremove,
  270. [Tstat] rstat,
  271. [Twstat] rwstat,
  272. };
  273. char Eperm[] = "permission denied";
  274. char Enotdir[] = "not a directory";
  275. char Enotexist[] = "file does not exist";
  276. char Ebadaddr[] = "bad address";
  277. char Eattn[] = "can't get modem's attention";
  278. char Edial[] = "can't dial";
  279. char Enoauth[] = "telco: authentication not required";
  280. char Eisopen[] = "file already open for I/O";
  281. char Enodev[] = "no free modems";
  282. char Enostream[] = "stream closed prematurely";
  283. void
  284. usage(void)
  285. {
  286. fprint(2, "usage: %s [-vp] [-i srcid] dev ...\n", argv0);
  287. exits("usage");
  288. }
  289. void
  290. notifyf(void *a, char *s)
  291. {
  292. USED(a);
  293. if(strncmp(s, "interrupt", 9) == 0)
  294. noted(NCONT);
  295. noted(NDFLT);
  296. }
  297. void
  298. main(int argc, char *argv[])
  299. {
  300. int p[2];
  301. int fd;
  302. char buf[10];
  303. Dev *d;
  304. ARGBEGIN{
  305. case 'p':
  306. pulsed = 1;
  307. break;
  308. case 'v':
  309. verbose = 1;
  310. break;
  311. case 'i':
  312. srcid = ARGF();
  313. break;
  314. case 's':
  315. maxspeed = atoi(ARGF());
  316. break;
  317. case 'n':
  318. answer = 0;
  319. break;
  320. default:
  321. usage();
  322. }ARGEND
  323. if(argc == 0)
  324. usage();
  325. if(argc > Ndev)
  326. argc = Ndev;
  327. if(pipe(p) < 0)
  328. error("pipe failed");
  329. notify(notifyf);
  330. fmtinstall('F', fcallfmt);
  331. user = getuser();
  332. switch(rfork(RFFDG|RFPROC|RFREND|RFNOTEG)){
  333. case -1:
  334. error("fork");
  335. case 0:
  336. close(p[1]);
  337. mfd[0] = mfd[1] = p[0];
  338. break;
  339. default:
  340. close(p[0]);
  341. fd = create("/srv/telco", OWRITE, 0666);
  342. if(fd < 0)
  343. error("create of /srv/telco failed");
  344. sprint(buf, "%d", p[1]);
  345. if(write(fd, buf, strlen(buf)) < 0)
  346. error("writing /srv/telco");
  347. close(fd);
  348. if(mount(p[1], -1, "/net", MBEFORE, "") < 0)
  349. error("mount failed");
  350. exits(0);
  351. }
  352. dev = mallocz(argc*sizeof(Dev), 1);
  353. for(ndev = 0; ndev < argc; ndev++){
  354. d = &dev[ndev];
  355. d->path = argv[ndev];
  356. d->rp = d->wp = d->rbuf;
  357. monitor(d);
  358. d->open++;
  359. onhook(d);
  360. d->open--;
  361. }
  362. io();
  363. }
  364. /*
  365. * generate a stat structure for a qid
  366. */
  367. int
  368. devstat(Dir *dir, uint8_t *buf, int nbuf)
  369. {
  370. Dev *d;
  371. int t;
  372. static char tmp[10][32];
  373. static int ntmp;
  374. t = TYPE(dir->qid);
  375. if(t != Qlvl3)
  376. dir->name = names[t];
  377. else{
  378. dir->name = tmp[ntmp % nelem(tmp)];
  379. sprint(dir->name, "%lud", DEV(dir->qid));
  380. ntmp++;
  381. }
  382. dir->mode = 0755;
  383. dir->uid = user;
  384. dir->gid = user;
  385. dir->muid = user;
  386. if(t >= Qlvl3){
  387. d = &dev[DEV(dir->qid)];
  388. if(d->open){
  389. dir->mode = d->perm;
  390. dir->uid = d->user;
  391. }
  392. }
  393. if(dir->qid.type & QTDIR)
  394. dir->mode |= DMDIR;
  395. if(t == Qdata){
  396. d = &dev[DEV(dir->qid)];
  397. dir->length = d->wp - d->rp;
  398. if(dir->length < 0)
  399. dir->length += Nrbuf;
  400. } else
  401. dir->length = 0;
  402. dir->atime = time(0);
  403. dir->mtime = dir->atime;
  404. if(buf)
  405. return convD2M(dir, buf, nbuf);
  406. return 0;
  407. }
  408. /*
  409. * enumerate file's we can walk to from q
  410. */
  411. int
  412. devgen(Qid q, int i, Dir *d, uint8_t *buf, int nbuf)
  413. {
  414. static uint32_t v;
  415. d->qid.vers = v++;
  416. switch(TYPE(q)){
  417. case Qlvl1:
  418. if(i != 0)
  419. return -1;
  420. d->qid.type = QTDIR;
  421. d->qid.path = Qlvl2;
  422. break;
  423. case Qlvl2:
  424. switch(i){
  425. case -1:
  426. d->qid.type = QTDIR;
  427. d->qid.path = Qlvl1;
  428. break;
  429. case 0:
  430. d->qid.type = QTFILE;
  431. d->qid.path = Qclone;
  432. break;
  433. default:
  434. if(i > ndev)
  435. return -1;
  436. d->qid.type = QTDIR;
  437. d->qid.path = MKQID(Qlvl3, i-1);
  438. break;
  439. }
  440. break;
  441. case Qlvl3:
  442. switch(i){
  443. case -1:
  444. d->qid.type = QTDIR;
  445. d->qid.path = Qlvl2;
  446. break;
  447. case 0:
  448. d->qid.type = QTFILE;
  449. d->qid.path = MKQID(Qdata, DEV(q));
  450. break;
  451. case 1:
  452. d->qid.type = QTFILE;
  453. d->qid.path = MKQID(Qctl, DEV(q));
  454. break;
  455. default:
  456. return -1;
  457. }
  458. break;
  459. default:
  460. return -1;
  461. }
  462. return devstat(d, buf, nbuf);
  463. }
  464. char*
  465. rversion(Fid *)
  466. {
  467. Fid *f;
  468. for(f = fids; f; f = f->next)
  469. if(f->busy)
  470. rclunk(f);
  471. if(thdr.msize < 256)
  472. return "version: message size too small";
  473. messagesize = thdr.msize;
  474. if(messagesize > sizeof mdata)
  475. messagesize = sizeof mdata;
  476. rhdr.msize = messagesize;
  477. if(strncmp(thdr.version, "9P2000", 6) != 0)
  478. return "unrecognized 9P version";
  479. rhdr.version = "9P2000";
  480. return 0;
  481. }
  482. char*
  483. rflush(Fid *f)
  484. {
  485. Request *r, **l;
  486. Dev *d;
  487. USED(f);
  488. for(d = dev; d < &dev[ndev]; d++){
  489. lock(d);
  490. for(l = &d->r; r = *l; l = &r->next)
  491. if(r->tag == thdr.oldtag){
  492. *l = r->next;
  493. free(r);
  494. break;
  495. }
  496. unlock(d);
  497. }
  498. return 0;
  499. }
  500. char *
  501. rauth(Fid *f)
  502. {
  503. USED(f);
  504. return Enoauth;
  505. }
  506. char*
  507. rattach(Fid *f)
  508. {
  509. f->busy = 1;
  510. f->qid.type = QTDIR;
  511. f->qid.path = Qlvl1;
  512. f->qid.vers = 0;
  513. rhdr.qid = f->qid;
  514. if(thdr.uname[0])
  515. f->user = strdup(thdr.uname);
  516. else
  517. f->user = "none";
  518. return 0;
  519. }
  520. char*
  521. rwalk(Fid *f)
  522. {
  523. Fid *nf;
  524. int i, nqid;
  525. char *name, *err;
  526. Dir dir;
  527. Qid q;
  528. nf = nil;
  529. if(thdr.fid != thdr.newfid){
  530. if(f->open)
  531. return Eisopen;
  532. if(f->busy == 0)
  533. return Enotexist;
  534. nf = newfid(thdr.newfid);
  535. nf->busy = 1;
  536. nf->open = 0;
  537. nf->qid = f->qid;
  538. nf->user = strdup(f->user);
  539. f = nf; /* walk f */
  540. }
  541. err = nil;
  542. dir.qid = f->qid;
  543. nqid = 0;
  544. if(thdr.nwname > 0){
  545. for(; nqid < thdr.nwname; nqid++) {
  546. if((dir.qid.type & QTDIR) == 0){
  547. err = Enotdir;
  548. break;
  549. }
  550. name = thdr.wname[nqid];
  551. if(strcmp(name, ".") == 0){
  552. /* nothing to do */
  553. }else if(strcmp(name, "..") == 0) {
  554. if(devgen(f->qid, -1, &dir, 0, 0) < 0)
  555. break;
  556. }
  557. else{
  558. q = dir.qid;
  559. for(i = 0;; i++){
  560. if(devgen(q, i, &dir, 0, 0) < 0)
  561. goto Out;
  562. if(strcmp(name, dir.name) == 0)
  563. break;
  564. }
  565. }
  566. rhdr.wqid[nqid] = dir.qid;
  567. }
  568. Out:
  569. if(nqid == 0 && err == nil)
  570. err = Enotexist;
  571. if(nf != nil && thdr.fid != thdr.newfid && nqid < thdr.nwname)
  572. rclunk(nf);
  573. }
  574. rhdr.nwqid = nqid;
  575. if(nqid > 0 && nqid == thdr.nwname)
  576. f->qid = dir.qid;
  577. return err;
  578. }
  579. char *
  580. ropen(Fid *f)
  581. {
  582. Dev *d;
  583. int mode, t;
  584. if(f->open)
  585. return Eisopen;
  586. mode = thdr.mode;
  587. mode &= OPERM;
  588. if(f->qid.type & QTDIR){
  589. if(mode != OREAD)
  590. return Eperm;
  591. rhdr.qid = f->qid;
  592. return 0;
  593. }
  594. if(mode==OEXEC)
  595. return Eperm;
  596. t = TYPE(f->qid);
  597. if(t == Qclone){
  598. for(d = dev; d < &dev[ndev]; d++)
  599. if(d->open == 0)
  600. break;
  601. if(d == &dev[ndev])
  602. return Enodev;
  603. f->qid.path = MKQID(Qctl, d-dev);
  604. t = Qctl;
  605. }
  606. switch(t){
  607. case Qdata:
  608. case Qctl:
  609. d = &dev[DEV(f->qid)];
  610. if(d->open == 0){
  611. d->user = strdup(f->user);
  612. d->perm = 0660;
  613. }else {
  614. if(mode==OWRITE || mode==ORDWR)
  615. if(!perm(f, d, Pwrite))
  616. return Eperm;
  617. if(mode==OREAD || mode==ORDWR)
  618. if(!perm(f, d, Pread))
  619. return Eperm;
  620. }
  621. d->open++;
  622. break;
  623. }
  624. rhdr.qid = f->qid;
  625. rhdr.iounit = messagesize - IOHDRSZ;
  626. f->open = 1;
  627. return 0;
  628. }
  629. char *
  630. rcreate(Fid *f)
  631. {
  632. USED(f);
  633. return Eperm;
  634. }
  635. /*
  636. * intercept a note
  637. */
  638. void
  639. takeanote(void *u, char *note)
  640. {
  641. USED(u);
  642. if(strstr(note, "flushed"))
  643. noted(NCONT);
  644. noted(NDFLT);
  645. }
  646. char*
  647. rread(Fid *f)
  648. {
  649. char *buf;
  650. int32_t off, start;
  651. int i, m, n, cnt, t;
  652. Dir dir;
  653. char num[32];
  654. Dev *d;
  655. Request *r;
  656. n = 0;
  657. rhdr.count = 0;
  658. off = thdr.offset;
  659. cnt = thdr.count;
  660. buf = rhdr.data;
  661. t = TYPE(f->qid);
  662. switch(t){
  663. default:
  664. start = 0;
  665. for(i = 0; n < cnt; i++){
  666. m = devgen(f->qid, i, &dir, (uint8_t*)buf+n, cnt-n);
  667. if(m <= BIT16SZ)
  668. break;
  669. if(start >= off)
  670. n += m;
  671. start += m;
  672. }
  673. break;
  674. case Qctl:
  675. i = sprint(num, "%lud", DEV(f->qid));
  676. if(off < i){
  677. n = cnt;
  678. if(off + n > i)
  679. n = i - off;
  680. memmove(buf, num + off, n);
  681. } else
  682. n = 0;
  683. break;
  684. case Qdata:
  685. d = &dev[DEV(f->qid)];
  686. r = mallocz(sizeof(Request), 1);
  687. r->tag = thdr.tag;
  688. r->count = thdr.count;
  689. r->fid = f;
  690. r->flushed = 0;
  691. lock(d);
  692. if(d->r)
  693. d->rlast->next = r;
  694. else
  695. d->r = r;
  696. d->rlast = r;
  697. serve(d);
  698. unlock(d);
  699. return "";
  700. }
  701. rhdr.count = n;
  702. return 0;
  703. }
  704. char *cmsg = "connect ";
  705. int clen;
  706. char*
  707. rwrite(Fid *f)
  708. {
  709. Dev *d;
  710. uint32_t off;
  711. int cnt;
  712. char *cp;
  713. char buf[64];
  714. off = thdr.offset;
  715. cnt = thdr.count;
  716. switch(TYPE(f->qid)){
  717. default:
  718. return "file is a directory";
  719. case Qctl:
  720. d = &dev[DEV(f->qid)];
  721. clen = strlen(cmsg);
  722. if(cnt < clen || strncmp(thdr.data, cmsg, clen) != 0){
  723. /*
  724. * send control message to real control file
  725. */
  726. if(seek(d->ctl, off, 0) < 0 || write(d->ctl, thdr.data, cnt) < 0){
  727. errstr(errbuf, sizeof errbuf);
  728. return errbuf;
  729. }
  730. } else {
  731. /*
  732. * connect
  733. */
  734. cnt -= clen;
  735. if(cnt >= sizeof(buf))
  736. cnt = sizeof(buf) - 1;
  737. if(cnt < 0)
  738. return Ebadaddr;
  739. strncpy(buf, &thdr.data[clen], cnt);
  740. buf[cnt] = 0;
  741. cp = dialout(d, buf);
  742. if(cp)
  743. return cp;
  744. }
  745. rhdr.count = cnt;
  746. break;
  747. case Qdata:
  748. d = &dev[DEV(f->qid)];
  749. if(write(d->data, thdr.data, cnt) < 0){
  750. errstr(errbuf, sizeof errbuf);
  751. return errbuf;
  752. }
  753. rhdr.count = cnt;
  754. break;
  755. }
  756. return 0;
  757. }
  758. char *
  759. rclunk(Fid *f)
  760. {
  761. Dev *d;
  762. if(f->open)
  763. switch(TYPE(f->qid)){
  764. case Qdata:
  765. case Qctl:
  766. d = &dev[DEV(f->qid)];
  767. if(d->open == 1)
  768. onhook(d);
  769. d->open--;
  770. break;
  771. }
  772. free(f->user);
  773. f->busy = 0;
  774. f->open = 0;
  775. return 0;
  776. }
  777. char *
  778. rremove(Fid *f)
  779. {
  780. USED(f);
  781. return Eperm;
  782. }
  783. char *
  784. rstat(Fid *f)
  785. {
  786. Dir d;
  787. d.qid = f->qid;
  788. rhdr.stat = statbuf;
  789. rhdr.nstat = devstat(&d, statbuf, sizeof statbuf);
  790. return 0;
  791. }
  792. char *
  793. rwstat(Fid *f)
  794. {
  795. Dev *d;
  796. Dir dir;
  797. if(TYPE(f->qid) < Qlvl3)
  798. return Eperm;
  799. convM2D(thdr.stat, thdr.nstat, &dir, rhdr.data); /* rhdr.data is a known place to scribble */
  800. d = &dev[DEV(f->qid)];
  801. /*
  802. * To change mode, must be owner
  803. */
  804. if(d->perm != dir.mode){
  805. if(strcmp(f->user, d->user) != 0)
  806. if(strcmp(f->user, user) != 0)
  807. return Eperm;
  808. }
  809. /* all ok; do it */
  810. d->perm = dir.mode & ~DMDIR;
  811. return 0;
  812. }
  813. Fid *
  814. newfid(int fid)
  815. {
  816. Fid *f, *ff;
  817. ff = 0;
  818. for(f = fids; f; f = f->next)
  819. if(f->fid == fid)
  820. return f;
  821. else if(!ff && !f->busy)
  822. ff = f;
  823. if(ff){
  824. ff->fid = fid;
  825. return ff;
  826. }
  827. f = emalloc(sizeof *f);
  828. f->fid = fid;
  829. f->next = fids;
  830. fids = f;
  831. return f;
  832. }
  833. /*
  834. * read fs requests and dispatch them
  835. */
  836. void
  837. io(void)
  838. {
  839. char *err;
  840. int n;
  841. for(;;){
  842. /*
  843. * reading from a pipe or a network device
  844. * will give an error after a few eof reads
  845. * however, we cannot tell the difference
  846. * between a zero-length read and an interrupt
  847. * on the processes writing to us,
  848. * so we wait for the error
  849. */
  850. n = read9pmsg(mfd[0], mdata, messagesize);
  851. if(n == 0)
  852. continue;
  853. if(n < 0)
  854. error("mount read");
  855. if(convM2S(mdata, n, &thdr) != n)
  856. error("convM2S error");
  857. rhdr.data = (char*)mdata + IOHDRSZ;
  858. if(!fcalls[thdr.type])
  859. err = "bad fcall type";
  860. else
  861. err = (*fcalls[thdr.type])(newfid(thdr.fid));
  862. if(err){
  863. if(*err == 0)
  864. continue; /* assigned to a slave */
  865. rhdr.type = Rerror;
  866. rhdr.ename = err;
  867. }else{
  868. rhdr.type = thdr.type + 1;
  869. rhdr.fid = thdr.fid;
  870. }
  871. rhdr.tag = thdr.tag;
  872. n = convS2M(&rhdr, mdata, messagesize);
  873. if(write(mfd[1], mdata, n) != n)
  874. error("mount write");
  875. }
  876. }
  877. int
  878. perm(Fid *f, Dev *d, int p)
  879. {
  880. if((p*Pother) & d->perm)
  881. return 1;
  882. if(strcmp(f->user, user)==0 && ((p*Pgroup) & d->perm))
  883. return 1;
  884. if(strcmp(f->user, d->user)==0 && ((p*Powner) & d->perm))
  885. return 1;
  886. return 0;
  887. }
  888. void
  889. error(char *s)
  890. {
  891. fprint(2, "%s: %s: %r\n", argv0, s);
  892. syslog(0, LOGFILE, "%s: %r", s);
  893. remove("/srv/telco");
  894. postnote(PNGROUP, getpid(), "exit");
  895. exits(s);
  896. }
  897. void *
  898. emalloc(uint32_t n)
  899. {
  900. void *p;
  901. p = mallocz(n, 1);
  902. if(!p)
  903. error("out of memory");
  904. return p;
  905. }
  906. void *
  907. erealloc(void *p, uint32_t n)
  908. {
  909. p = realloc(p, n);
  910. if(!p)
  911. error("out of memory");
  912. return p;
  913. }
  914. /*
  915. * send bytes to modem
  916. */
  917. int
  918. send(Dev *d, char *x)
  919. {
  920. if(verbose)
  921. syslog(0, LOGFILE, "->%s", x);
  922. return write(d->data, x, strlen(x));
  923. }
  924. /*
  925. * apply a string of commands to modem
  926. */
  927. int
  928. apply(Dev *d, char *s, char *substr, int secs)
  929. {
  930. char buf[128];
  931. char *p;
  932. int c, m;
  933. p = buf;
  934. m = Ok;
  935. while(*s){
  936. c = *p++ = *s++;
  937. if(c == '\r' || *s == 0){
  938. if(c != '\r')
  939. *p++ = '\r';
  940. *p = 0;
  941. if(send(d, buf) < 0)
  942. return Failure;
  943. m = readmsg(d, secs, substr);
  944. p = buf;
  945. }
  946. }
  947. return m;
  948. }
  949. /*
  950. * apply a command type
  951. */
  952. int
  953. applyspecial(Dev *d, int index)
  954. {
  955. char *cmd;
  956. cmd = d->t->commands[index];
  957. if(cmd == 0 && d->baset)
  958. cmd = d->baset->commands[index];
  959. if(cmd == 0)
  960. return Failure;
  961. return apply(d, cmd, 0, 2);
  962. }
  963. /*
  964. * get modem into command mode if it isn't already
  965. */
  966. int
  967. attention(Dev *d)
  968. {
  969. int i;
  970. for(i = 0; i < 2; i++){
  971. sleep(250);
  972. if(send(d, "+") < 0)
  973. continue;
  974. sleep(250);
  975. if(send(d, "+") < 0)
  976. continue;
  977. sleep(250);
  978. if(send(d, "+") < 0)
  979. continue;
  980. sleep(250);
  981. readmsg(d, 0, 0);
  982. if(apply(d, "ATZH0", 0, 2) == Ok)
  983. return Ok;
  984. }
  985. return Failure;
  986. }
  987. int portspeed[] = { 56000, 38400, 19200, 14400, 9600, 4800, 2400, 1200, 600, 300, 0 };
  988. /*
  989. * get the modem's type and speed
  990. */
  991. char*
  992. modemtype(Dev *d, int limit, int fax)
  993. {
  994. int *p;
  995. Type *t, *bt;
  996. char buf[28];
  997. d->t = typetab;
  998. d->baset = 0;
  999. /* assume we're at a good speed, try getting attention a few times */
  1000. attention(d);
  1001. /* find a common port rate */
  1002. for(p = portspeed; *p; p++){
  1003. if(*p > limit)
  1004. continue;
  1005. setspeed(d, *p);
  1006. if(attention(d) == Ok)
  1007. break;
  1008. }
  1009. if(*p == 0)
  1010. return Eattn;
  1011. d->speed = *p;
  1012. if(verbose)
  1013. syslog(0, LOGFILE, "port speed %d", *p);
  1014. /*
  1015. * basic Hayes commands everyone implements (we hope)
  1016. * Q0 = report result codes
  1017. * V1 = full word result codes
  1018. * E0 = don't echo commands
  1019. * M1 = speaker on until on-line
  1020. * S0=0 = autoanswer off
  1021. */
  1022. if(apply(d, "ATQ0V1E0M1S0=0", 0, 2) != Ok)
  1023. return Eattn;
  1024. /* find modem type */
  1025. for(t = typetab; t->name; t++){
  1026. if(t->ident == 0 || t->response == 0)
  1027. continue;
  1028. if(apply(d, t->ident, t->response, 2) == Found)
  1029. break;
  1030. readmsg(d, 0, 0);
  1031. }
  1032. readmsg(d, 0, 0);
  1033. if(t->name){
  1034. d->t = t;
  1035. if(t->basetype){
  1036. for(bt = typetab; bt->name; bt++)
  1037. if(strcmp(bt->name, t->basetype) == 0)
  1038. break;
  1039. if(bt->name)
  1040. d->baset = bt;
  1041. }
  1042. }
  1043. if(verbose)
  1044. syslog(0, LOGFILE, "modem %s", d->t->name);
  1045. /* try setting fax modes */
  1046. d->fclass = 0;
  1047. if(fax){
  1048. /* set up fax parameters */
  1049. if(applyspecial(d, Cfclass2) != Failure)
  1050. d->fclass = 2;
  1051. /* setup a source id */
  1052. if(srcid){
  1053. sprint(buf, "AT+FLID=\"%s\"", srcid);
  1054. apply(d, buf, 0, 2);
  1055. }
  1056. /* allow both data and fax calls in */
  1057. apply(d, "AT+FAA=1", 0, 2);
  1058. } else
  1059. applyspecial(d, Cfclass0);
  1060. return 0;
  1061. }
  1062. /*
  1063. * a process to read input from a modem.
  1064. */
  1065. void
  1066. monitor(Dev *d)
  1067. {
  1068. int n;
  1069. char *p;
  1070. char file[256];
  1071. int background;
  1072. background = 0;
  1073. d->ctl = d->data = -1;
  1074. for(;;){
  1075. lock(d);
  1076. sprint(file, "%sctl", d->path);
  1077. d->ctl = open(file, ORDWR);
  1078. if(d->ctl < 0)
  1079. error("opening ctl");
  1080. d->data = open(d->path, ORDWR);
  1081. if(d->data < 0)
  1082. error("opening data");
  1083. d->wp = d->rp = d->rbuf;
  1084. unlock(d);
  1085. if(!background){
  1086. background = 1;
  1087. switch(d->pid = rfork(RFPROC|RFMEM)){
  1088. case -1:
  1089. error("out of processes");
  1090. case 0:
  1091. break;
  1092. default:
  1093. return;
  1094. }
  1095. }
  1096. /* wait for ring or off hook */
  1097. while(d->open == 0){
  1098. d->rp = d->rbuf;
  1099. p = d->wp;
  1100. n = read(d->data, p, 1);
  1101. if(n < 1)
  1102. continue;
  1103. if(p < &d->rbuf[Nrbuf] - 2)
  1104. d->wp++;
  1105. if(*p == '\r' || *p == '\n'){
  1106. *(p+1) = 0;
  1107. if(verbose)
  1108. syslog(0, LOGFILE, "<:-%s", d->rp);
  1109. if(answer && strncmp(d->rp, "RING", 4) == 0){
  1110. receiver(d);
  1111. continue;
  1112. }
  1113. if(d->open == 0)
  1114. d->wp = d->rbuf;
  1115. }
  1116. }
  1117. /* shuttle bytes till on hook */
  1118. while(d->open){
  1119. if(d->wp >= d->rp)
  1120. n = &d->rbuf[Nrbuf] - d->wp;
  1121. else
  1122. n = d->rp - d->wp - 1;
  1123. if(n > 0)
  1124. n = read(d->data, d->wp, n);
  1125. else {
  1126. read(d->data, file, sizeof(file));
  1127. continue;
  1128. }
  1129. if(n < 0)
  1130. break;
  1131. lock(d);
  1132. if(d->wp + n >= &d->rbuf[Nrbuf])
  1133. d->wp = d->rbuf;
  1134. else
  1135. d->wp += n;
  1136. serve(d);
  1137. unlock(d);
  1138. }
  1139. close(d->ctl);
  1140. close(d->data);
  1141. }
  1142. }
  1143. /*
  1144. * get bytes input by monitor() (only routine that changes d->rp)
  1145. */
  1146. int
  1147. getinput(Dev *d, char *buf, int n)
  1148. {
  1149. char *p;
  1150. int i;
  1151. p = buf;
  1152. while(n > 0){
  1153. if(d->wp == d->rp)
  1154. break;
  1155. if(d->wp < d->rp)
  1156. i = &d->rbuf[Nrbuf] - d->rp;
  1157. else
  1158. i = d->wp - d->rp;
  1159. if(i > n)
  1160. i = n;
  1161. memmove(p, d->rp, i);
  1162. if(d->rp + i == &d->rbuf[Nrbuf])
  1163. d->rp = d->rbuf;
  1164. else
  1165. d->rp += i;
  1166. n -= i;
  1167. p += i;
  1168. }
  1169. return p - buf;
  1170. }
  1171. /*
  1172. * fulfill a read request (we assume d is locked)
  1173. */
  1174. void
  1175. serve(Dev *d)
  1176. {
  1177. Request *r;
  1178. int n;
  1179. Fcall rhdr;
  1180. uint8_t *mdata;
  1181. char *buf;
  1182. mdata = malloc(messagesize);
  1183. buf = malloc(messagesize-IOHDRSZ);
  1184. for(;;){
  1185. if(d->r == 0 || d->rp == d->wp)
  1186. break;
  1187. r = d->r;
  1188. if(r->count > sizeof(buf))
  1189. r->count = sizeof(buf);
  1190. n = getinput(d, buf, r->count);
  1191. if(n == 0)
  1192. break;
  1193. d->r = r->next;
  1194. rhdr.type = Rread;
  1195. rhdr.fid = r->fid->fid;
  1196. rhdr.tag = r->tag;
  1197. rhdr.data = buf;
  1198. rhdr.count = n;
  1199. n = convS2M(&rhdr, mdata, messagesize);
  1200. if(write(mfd[1], mdata, n) != n)
  1201. fprint(2, "telco: error writing\n");
  1202. free(r);
  1203. }
  1204. free(mdata);
  1205. free(buf);
  1206. }
  1207. /*
  1208. * dial a number
  1209. */
  1210. char*
  1211. dialout(Dev *d, char *number)
  1212. {
  1213. int i, m, compress, rateadjust, speed, fax;
  1214. char *err;
  1215. char *field[5];
  1216. char dialstr[128];
  1217. compress = Ok;
  1218. rateadjust = Failure;
  1219. speed = maxspeed;
  1220. fax = Failure;
  1221. m = getfields(number, field, 5, 1, "!");
  1222. for(i = 1; i < m; i++){
  1223. if(field[i][0] >= '0' && field[i][0] <= '9')
  1224. speed = atoi(field[i]);
  1225. else if(strcmp(field[i], "nocompress") == 0)
  1226. compress = Failure;
  1227. else if(strcmp(field[i], "fax") == 0)
  1228. fax = Ok;
  1229. }
  1230. syslog(0, LOGFILE, "dialing %s speed=%d %s", number, speed, fax==Ok?"fax":"");
  1231. err = modemtype(d, speed, fax == Ok);
  1232. if(err)
  1233. return err;
  1234. /*
  1235. * extented Hayes commands, meaning depends on modem (VGA all over again)
  1236. */
  1237. if(fax != Ok){
  1238. if(d->fclass != 0)
  1239. applyspecial(d, Cfclass0);
  1240. applyspecial(d, Cerrorcorrection);
  1241. if(compress == Ok)
  1242. compress = applyspecial(d, Ccompression);
  1243. if(compress != Ok)
  1244. rateadjust = applyspecial(d, Crateadjust);
  1245. }
  1246. applyspecial(d, Cflowctl);
  1247. /* dialout */
  1248. sprint(dialstr, "ATD%c%s\r", pulsed ? 'P' : 'T', number);
  1249. if(send(d, dialstr) < 0)
  1250. return Edial;
  1251. if(fax == Ok)
  1252. return 0; /* fax sender worries about the rest */
  1253. switch(readmsg(d, 120, 0)){
  1254. case Success:
  1255. break;
  1256. default:
  1257. return d->msgbuf;
  1258. }
  1259. /* change line rate if not compressing */
  1260. if(rateadjust == Ok)
  1261. setspeed(d, getspeed(d->msgbuf, d->speed));
  1262. return 0;
  1263. }
  1264. /*
  1265. * start a receiving process
  1266. */
  1267. void
  1268. receiver(Dev *d)
  1269. {
  1270. int fd;
  1271. char file[256];
  1272. char *argv[8];
  1273. int argc;
  1274. int pfd[2];
  1275. char *prog;
  1276. pipe(pfd);
  1277. switch(rfork(RFPROC|RFMEM|RFFDG|RFNAMEG)){
  1278. case -1:
  1279. return;
  1280. case 0:
  1281. fd = open("/srv/telco", ORDWR);
  1282. if(fd < 0){
  1283. syslog(0, LOGFILE, "can't open telco: %r");
  1284. exits(0);
  1285. }
  1286. if(mount(fd, -1, "/net", MAFTER, "", 'M') < 0){
  1287. syslog(0, LOGFILE, "can't mount: %r");
  1288. exits(0);
  1289. }
  1290. close(fd);
  1291. /* open connection through the file system interface */
  1292. sprint(file, "/net/telco/%ld/data", d - dev);
  1293. fd = open(file, ORDWR);
  1294. if(fd < 0){
  1295. syslog(0, LOGFILE, "can't open %s: %r", file);
  1296. exits(0);
  1297. }
  1298. /* let parent continue */
  1299. close(pfd[0]);
  1300. close(pfd[1]);
  1301. /* answer the phone and see what flavor call this is */
  1302. prog = "/bin/service/telcodata";
  1303. switch(apply(d, "ATA", "+FCON", 30)){
  1304. case Success:
  1305. break;
  1306. case Found:
  1307. prog = "/bin/service/telcofax";
  1308. break;
  1309. default:
  1310. syslog(0, LOGFILE, "bad ATA response");
  1311. exits(0);
  1312. }
  1313. /* fork a receiving process */
  1314. dup(fd, 0);
  1315. dup(fd, 1);
  1316. close(fd);
  1317. argc = 0;
  1318. argv[argc++] = strrchr(prog, '/')+1;
  1319. argv[argc++] = file;
  1320. argv[argc++] = dev->t->name;
  1321. argv[argc] = 0;
  1322. exec(prog, argv);
  1323. syslog(0, LOGFILE, "can't exec %s: %r\n", prog);
  1324. exits(0);
  1325. default:
  1326. /* wait till child gets the device open */
  1327. close(pfd[1]);
  1328. read(pfd[0], file, 1);
  1329. close(pfd[0]);
  1330. break;
  1331. }
  1332. }
  1333. /*
  1334. * hang up an connections in progress
  1335. */
  1336. void
  1337. onhook(Dev *d)
  1338. {
  1339. write(d->ctl, "d0", 2);
  1340. write(d->ctl, "r0", 2);
  1341. sleep(250);
  1342. write(d->ctl, "r1", 2);
  1343. write(d->ctl, "d1", 2);
  1344. modemtype(d, maxspeed, 1);
  1345. }
  1346. /*
  1347. * read till we see a message or we time out
  1348. */
  1349. int
  1350. readmsg(Dev *d, int secs, char *substr)
  1351. {
  1352. uint32_t start;
  1353. char *p;
  1354. int i, len;
  1355. Msg *pp;
  1356. int found = 0;
  1357. p = d->msgbuf;
  1358. len = sizeof(d->msgbuf) - 1;
  1359. for(start = time(0); time(0) <= start+secs;){
  1360. if(len && d->rp == d->wp){
  1361. sleep(100);
  1362. continue;
  1363. }
  1364. i = getinput(d, p, 1);
  1365. if(i == 0)
  1366. continue;
  1367. if(*p == '\n' || *p == '\r' || len == 0){
  1368. *p = 0;
  1369. if(verbose && p != d->msgbuf)
  1370. syslog(0, LOGFILE, "<-%s", d->msgbuf);
  1371. if(substr && strstr(d->msgbuf, substr))
  1372. found = 1;
  1373. for(pp = msgs; pp->text; pp++)
  1374. if(strncmp(pp->text, d->msgbuf, strlen(pp->text))==0)
  1375. return found ? Found : pp->type;
  1376. start = time(0);
  1377. p = d->msgbuf;
  1378. len = sizeof(d->msgbuf) - 1;
  1379. continue;
  1380. }
  1381. len--;
  1382. p++;
  1383. }
  1384. strcpy(d->msgbuf, "No response from modem");
  1385. return found ? Found : Noise;
  1386. }
  1387. /*
  1388. * get baud rate from a connect message
  1389. */
  1390. int
  1391. getspeed(char *msg, int speed)
  1392. {
  1393. char *p;
  1394. int s;
  1395. p = msg + sizeof("CONNECT") - 1;
  1396. while(*p == ' ' || *p == '\t')
  1397. p++;
  1398. s = atoi(p);
  1399. if(s <= 0)
  1400. return speed;
  1401. else
  1402. return s;
  1403. }
  1404. /*
  1405. * set speed and RTS/CTS modem flow control
  1406. */
  1407. void
  1408. setspeed(Dev *d, int baud)
  1409. {
  1410. char buf[32];
  1411. if(d->ctl < 0)
  1412. return;
  1413. sprint(buf, "b%d", baud);
  1414. write(d->ctl, buf, strlen(buf));
  1415. write(d->ctl, "m1", 2);
  1416. }